diff --git a/README b/README new file mode 100644 index 0000000..75574cb --- /dev/null +++ b/README @@ -0,0 +1,19 @@ +Nemo Transfer Engine + +Simple engine for keeping track of transfers (sync, download, upload) and providing plugin mechanism for +share plugins. + +Transfer engine provides D-Bus API for managing the database and querying transfer information. + +Building: + +qmake +make + +Generating Docs: +make sure qdoc3 is installed and run: + +make docs + + + diff --git a/dbus/org.nemo.transferengine.service b/dbus/org.nemo.transferengine.service new file mode 100644 index 0000000..40c4d14 --- /dev/null +++ b/dbus/org.nemo.transferengine.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Interface=/org/nemo/transferengine +Name=org.nemo.transferengine +Exec=/usr/bin/nemo-transfer-engine diff --git a/dbus/org.nemo.transferengine.xml b/dbus/org.nemo.transferengine.xml new file mode 100644 index 0000000..19ecc18 --- /dev/null +++ b/dbus/org.nemo.transferengine.xml @@ -0,0 +1,122 @@ + + + + + + # Share API + + + + + + + + + + + + + + + + + + + # create Sync Entry + + + + + + + + + + + # create Download entry + + + + + + + + + + + + + + # API for updating either download or sync + + + + + + # Mark specific upload or a sync as started. + + + + + # Restart upload or a sync + + + + + # Mark a specific upload or a sync transfer as finished + # if success == false, then the reason for failure should + # be set to human readable message + + + + + + + # Get a list of transfers + + + + + + # Get a list of transfer methods such as FB, Twitter, BT, NFC, etc + + + + + + # clear all unfinished transfers + + + # cancel a specific transfer + + + + + # enable or disable notifications + + + + + # Query if notifications are enabled + + + + + # Signals for indicating changes in transfers + + + + + + + + + + + + + + + + diff --git a/doc/compat.qdocconf b/doc/compat.qdocconf new file mode 100644 index 0000000..d19072f --- /dev/null +++ b/doc/compat.qdocconf @@ -0,0 +1,31 @@ +#alias.i = e +alias.include = input + +macro.0 = "\\\\0" +macro.b = "\\\\b" +macro.n = "\\\\n" +macro.r = "\\\\r" +#macro.i = "\\o" +macro.i11 = "\\o{1,1}" +macro.i12 = "\\o{1,2}" +macro.i13 = "\\o{1,3}" +macro.i14 = "\\o{1,4}" +macro.i15 = "\\o{1,5}" +macro.i16 = "\\o{1,6}" +macro.i17 = "\\o{1,7}" +macro.i18 = "\\o{1,8}" +macro.i19 = "\\o{1,9}" +macro.i21 = "\\o{2,1}" +macro.i31 = "\\o{3,1}" +macro.i41 = "\\o{4,1}" +macro.i51 = "\\o{5,1}" +macro.i61 = "\\o{6,1}" +macro.i71 = "\\o{7,1}" +macro.i81 = "\\o{8,1}" +macro.i91 = "\\o{9,1}" +macro.img = "\\image" +macro.endquote = "\\endquotation" +macro.relatesto = "\\relates" + +spurious = "Missing comma in .*" \ + "Missing pattern .*" diff --git a/doc/config/compat.qdocconf b/doc/config/compat.qdocconf new file mode 100644 index 0000000..d19072f --- /dev/null +++ b/doc/config/compat.qdocconf @@ -0,0 +1,31 @@ +#alias.i = e +alias.include = input + +macro.0 = "\\\\0" +macro.b = "\\\\b" +macro.n = "\\\\n" +macro.r = "\\\\r" +#macro.i = "\\o" +macro.i11 = "\\o{1,1}" +macro.i12 = "\\o{1,2}" +macro.i13 = "\\o{1,3}" +macro.i14 = "\\o{1,4}" +macro.i15 = "\\o{1,5}" +macro.i16 = "\\o{1,6}" +macro.i17 = "\\o{1,7}" +macro.i18 = "\\o{1,8}" +macro.i19 = "\\o{1,9}" +macro.i21 = "\\o{2,1}" +macro.i31 = "\\o{3,1}" +macro.i41 = "\\o{4,1}" +macro.i51 = "\\o{5,1}" +macro.i61 = "\\o{6,1}" +macro.i71 = "\\o{7,1}" +macro.i81 = "\\o{8,1}" +macro.i91 = "\\o{9,1}" +macro.img = "\\image" +macro.endquote = "\\endquotation" +macro.relatesto = "\\relates" + +spurious = "Missing comma in .*" \ + "Missing pattern .*" diff --git a/doc/config/images/.directory b/doc/config/images/.directory new file mode 100644 index 0000000..3b070b5 --- /dev/null +++ b/doc/config/images/.directory @@ -0,0 +1,3 @@ +[Dolphin] +PreviewsShown=true +Timestamp=2012,12,12,16,59,29 diff --git a/doc/config/images/breadcrumb.png b/doc/config/images/breadcrumb.png new file mode 100644 index 0000000..128bcbd Binary files /dev/null and b/doc/config/images/breadcrumb.png differ diff --git a/doc/config/images/bullet_dn.png b/doc/config/images/bullet_dn.png new file mode 100644 index 0000000..95e8159 Binary files /dev/null and b/doc/config/images/bullet_dn.png differ diff --git a/doc/config/images/bullet_gt.png b/doc/config/images/bullet_gt.png new file mode 100644 index 0000000..0d94209 Binary files /dev/null and b/doc/config/images/bullet_gt.png differ diff --git a/doc/config/images/bullet_sq.png b/doc/config/images/bullet_sq.png new file mode 100644 index 0000000..7bdd7ff Binary files /dev/null and b/doc/config/images/bullet_sq.png differ diff --git a/doc/config/images/bullet_up.png b/doc/config/images/bullet_up.png new file mode 100644 index 0000000..1923634 Binary files /dev/null and b/doc/config/images/bullet_up.png differ diff --git a/doc/config/macros.qdocconf b/doc/config/macros.qdocconf new file mode 100644 index 0000000..2262daa --- /dev/null +++ b/doc/config/macros.qdocconf @@ -0,0 +1,37 @@ +macro.aacute.HTML = "á" +macro.Aring.HTML = "Å" +macro.aring.HTML = "å" +macro.Auml.HTML = "Ä" +macro.author = "\\bold{Author:}" +macro.br.HTML = "
" +macro.BR.HTML = "
" +macro.copyright.HTML = "©" +macro.eacute.HTML = "é" +macro.gui = "\\bold" +macro.hr.HTML = "
" +macro.iacute.HTML = "í" +macro.key = "\\bold" +macro.menu = "\\bold" +macro.note = "\\bold{Note:}" +macro.oslash.HTML = "ø" +macro.ouml.HTML = "ö" +macro.QA = "\\e{Qt Assistant}" +macro.QD = "\\e{Qt Designer}" +macro.QL = "\\e{Qt Linguist}" +macro.QQV = "\\e{Qt QML Viewer}" +macro.param = "\\e" +macro.raisedaster.HTML = "*" +macro.rarrow.HTML = "→" +macro.reg.HTML = "®" +macro.return = "Returns" +macro.starslash = "\\c{*/}" +macro.begincomment = "\\c{/*}" +macro.endcomment = "\\c{*/}" +macro.uuml.HTML = "ü" +macro.mdash.HTML = "—" + +macro.beginfloatleft.HTML = "
" +macro.beginfloatright.HTML = "
" +macro.endfloat.HTML = "
" +macro.clearfloat.HTML = "
" +macro.emptyspan.HTML = "" diff --git a/doc/config/qt-cpp-ignore.qdocconf b/doc/config/qt-cpp-ignore.qdocconf new file mode 100644 index 0000000..9b09a60 --- /dev/null +++ b/doc/config/qt-cpp-ignore.qdocconf @@ -0,0 +1,99 @@ +Cpp.ignoretokens = QAXFACTORY_EXPORT \ + QDESIGNER_COMPONENTS_LIBRARY \ + QDESIGNER_EXTENSION_LIBRARY \ + QDESIGNER_SDK_LIBRARY \ + QDESIGNER_SHARED_LIBRARY \ + QDESIGNER_UILIB_LIBRARY \ + QM_EXPORT_CANVAS \ + QM_EXPORT_DNS \ + QM_EXPORT_DOM \ + QM_EXPORT_FTP \ + QM_EXPORT_HTTP \ + QM_EXPORT_ICONVIEW \ + QM_EXPORT_NETWORK \ + QM_EXPORT_OPENGL \ + QM_EXPORT_OPENVG \ + QM_EXPORT_SQL \ + QM_EXPORT_TABLE \ + QM_EXPORT_WORKSPACE \ + QM_EXPORT_XML \ + QT_ASCII_CAST_WARN \ + QT_ASCII_CAST_WARN_CONSTRUCTOR \ + QT_BEGIN_HEADER \ + QT_DESIGNER_STATIC \ + QT_END_HEADER \ + QT_FASTCALL \ + QT_WIDGET_PLUGIN_EXPORT \ + Q_COMPAT_EXPORT \ + Q_CORE_EXPORT \ + Q_CORE_EXPORT_INLINE \ + Q_EXPLICIT \ + Q_EXPORT \ + Q_EXPORT_CODECS_CN \ + Q_EXPORT_CODECS_JP \ + Q_EXPORT_CODECS_KR \ + Q_EXPORT_PLUGIN \ + Q_GFX_INLINE \ + Q_AUTOTEST_EXPORT \ + QM_AUTOTEST_EXPORT \ + Q_GUI_EXPORT \ + Q_GUI_EXPORT_INLINE \ + Q_GUI_EXPORT_STYLE_CDE \ + Q_GUI_EXPORT_STYLE_COMPACT \ + Q_GUI_EXPORT_STYLE_MAC \ + Q_GUI_EXPORT_STYLE_MOTIF \ + Q_GUI_EXPORT_STYLE_MOTIFPLUS \ + Q_GUI_EXPORT_STYLE_PLATINUM \ + Q_GUI_EXPORT_STYLE_POCKETPC \ + Q_GUI_EXPORT_STYLE_SGI \ + Q_GUI_EXPORT_STYLE_WINDOWS \ + Q_GUI_EXPORT_STYLE_WINDOWSXP \ + QHELP_EXPORT \ + Q_INLINE_TEMPLATE \ + Q_INTERNAL_WIN_NO_THROW \ + Q_NETWORK_EXPORT \ + Q_OPENGL_EXPORT \ + Q_OPENVG_EXPORT \ + Q_OUTOFLINE_TEMPLATE \ + Q_SQL_EXPORT \ + Q_SVG_EXPORT \ + Q_SCRIPT_EXPORT \ + Q_SCRIPTTOOLS_EXPORT \ + Q_TESTLIB_EXPORT \ + Q_TYPENAME \ + Q_XML_EXPORT \ + Q_XMLSTREAM_EXPORT \ + Q_XMLPATTERNS_EXPORT \ + QDBUS_EXPORT \ + Q_DBUS_EXPORT \ + QT_BEGIN_NAMESPACE \ + QT_BEGIN_INCLUDE_NAMESPACE \ + QT_END_NAMESPACE \ + QT_END_INCLUDE_NAMESPACE \ + PHONON_EXPORT \ + Q_DECLARATIVE_EXPORT \ + Q_GADGET \ + QWEBKIT_EXPORT \ + Q_INVOKABLE +Cpp.ignoredirectives = Q_DECLARE_HANDLE \ + Q_DECLARE_INTERFACE \ + Q_DECLARE_METATYPE \ + Q_DECLARE_OPERATORS_FOR_FLAGS \ + Q_DECLARE_PRIVATE \ + Q_DECLARE_PUBLIC \ + Q_DECLARE_SHARED \ + Q_DECLARE_TR_FUNCTIONS \ + Q_DECLARE_TYPEINFO \ + Q_DISABLE_COPY \ + QT_FORWARD_DECLARE_CLASS \ + Q_DUMMY_COMPARISON_OPERATOR \ + Q_ENUMS \ + Q_FLAGS \ + Q_INTERFACES \ + __attribute__ \ + K_DECLARE_PRIVATE \ + PHONON_OBJECT \ + PHONON_HEIR \ + Q_PRIVATE_PROPERTY \ + Q_DECLARE_PRIVATE_D \ + Q_CLASSINFO diff --git a/doc/config/qt-defines.qdocconf b/doc/config/qt-defines.qdocconf new file mode 100644 index 0000000..50a355f --- /dev/null +++ b/doc/config/qt-defines.qdocconf @@ -0,0 +1,17 @@ +defines = Q_QDOC \ + QT_.*_SUPPORT \ + QT_.*_LIB \ + QT_COMPAT \ + QT_KEYPAD_NAVIGATION \ + QT_NO_EGL \ + QT3_SUPPORT \ + Q_WS_.* \ + Q_OS_.* \ + Q_BYTE_ORDER \ + QT_DEPRECATED \ + Q_NO_USING_KEYWORD \ + __cplusplus + +versionsym = QT_VERSION_STR + +codeindent = 1 diff --git a/doc/config/qt-html-default-styles.qdocconf b/doc/config/qt-html-default-styles.qdocconf new file mode 100644 index 0000000..af1d459 --- /dev/null +++ b/doc/config/qt-html-default-styles.qdocconf @@ -0,0 +1,27 @@ +# Define the location of the templates to use. Style sheets and scripts are +# specified relative to the template directory and will be copied into +# subdirectories of the output directory. + +HTML.templatedir = . + +HTML.stylesheets = style/offline.css + +HTML.scripts = + +# Files not referenced in any qdoc file +extraimages.HTML = breadcrumb.png \ + bullet_gt.png \ + bullet_dn.png \ + bullet_sq.png \ + bullet_up.png + +# Include the style sheets and scripts used. + +HTML.headerstyles = \ + " \n" + +HTML.headerscripts = + +HTML.endheader = \ + "\n" \ + "\n" diff --git a/doc/config/qt-html-templates.qdocconf b/doc/config/qt-html-templates.qdocconf new file mode 100644 index 0000000..b528e14 --- /dev/null +++ b/doc/config/qt-html-templates.qdocconf @@ -0,0 +1,43 @@ +include(qt-html-default-styles.qdocconf) + +HTML.postheader = \ + "
\n" \ + " \n" \ + "
\n" \ + "
    \n" \ + "
  • Home
  • \n" \ + " \n" + +HTML.postpostheader = \ + "
\n" \ + "
\n" \ + "
\n" \ + "
\n" + +HTML.footer = \ + "
\n" \ + " \n" \ + "
\n" \ + "
\n" \ + "
\n" \ + "

\n" \ + " © 2013 Jolla OY\n" \ + "

\n" \ + " All other trademarks are property of their respective owners.\n" \ + "
\n" \ + " This document may be used under the terms of the GNU\n" \ + " Free Documentation License version 1.3\n" \ + " as published by the Free Software Foundation.

\n" \ + "
\n" \ + +# Files not referenced in any qdoc file. +# See also extraimages.HTML +qhp.SailfishSilica.extraFiles = index.html \ + images/breadcrumb.png \ + images/bullet_gt.png \ + images/bullet_dn.png \ + images/bullet_sq.png \ + images/bullet_up.png \ + style/offline.css diff --git a/doc/config/style/offline.css b/doc/config/style/offline.css new file mode 100644 index 0000000..8d0da24 --- /dev/null +++ b/doc/config/style/offline.css @@ -0,0 +1,675 @@ +@media screen +{ + +/* basic elements */ + html + { + color: #000000; + background: #FFFFFF; + } + table + { + border-collapse: collapse; + border-spacing: 0; + } + fieldset, img + { + border: 0; + max-width:100%; + } + address, caption, cite, code, dfn, em, strong, th, var, optgroup + { + font-style: inherit; + font-weight: inherit; + } + del, ins + { + text-decoration: none; + } + ol li + { + list-style: decimal; + } + ul li + { + list-style: none; + } + caption, th + { + text-align: left; + } + h1, h2, h3, h4, h5, h6 + { + font-size: 100%; + } + q:before, q:after + { + content: ''; + } + abbr, acronym + { + border: 0; + font-variant: normal; + } + sup, sub + { + vertical-align: baseline; + } + tt, .qmlreadonly span, .qmldefault span + { + word-spacing:0.5em; + } + legend + { + color: #000000; + } + strong + { + font-weight: bold; + } + em + { + font-style: italic; + } + + body + { + margin-left: 0.5em; + margin-right: 0.5em; + font-family: sans-serif; + line-height: normal + } + a + { + color: #735704; + text-decoration: none; + } + hr + { + background-color: #E6E6E6; + border: 1px solid #E6E6E6; + height: 1px; + width: 100%; + text-align: left; + margin: 1.5em 0 1.5em 0; + } + + pre + { + border: 1px solid #DDDDDD; + -moz-border-radius: 0.7em 0.7em 0.7em 0.7em; + -webkit-border-radius: 0.7em 0.7em 0.7em 0.7em; + border-radius: 0.7em 0.7em 0.7em 0.7em; + margin: 0 1.5em 1em 1em; + padding: 1em 1em 1em 1em; + overflow-x: auto; + } + table, pre + { + -moz-border-radius: 0.7em 0.7em 0.7em 0.7em; + -webkit-border-radius: 0.7em 0.7em 0.7em 0.7em; + border-radius: 0.7em 0.7em 0.7em 0.7em; + background-color: #F6F6F6; + border: 1px solid #E6E6E6; + border-collapse: separate; + margin-bottom: 2.5em; + } + pre { + font-size: 90%; + display: block; + overflow:hidden; + } + thead + { + margin-top: 0.5em; + font-weight: bold + } + th + { + padding: 0.5em 1.5em 0.5em 1em; + background-color: #E1E1E1; + border-left: 1px solid #E6E6E6; + } + td + { + padding: 0.25em 1.5em 0.25em 1em; + } + + td.rightAlign + { + padding: 0.25em 0.5em 0.25em 1em; + } + table tr.odd + { + border-left: 1px solid #E6E6E6; + background-color: #F6F6F6; + color: #66666E; + } + table tr.even + { + border-left: 1px solid #E6E6E6; + background-color: #ffffff; + color: #66666E; + } + + div.float-left + { + float: left; margin-right: 2em + } + div.float-right + { + float: right; margin-left: 2em + } + + span.comment + { + color: #008B00; + } + span.string, span.char + { + color: #000084; + } + span.number + { + color: #a46200; + } + span.operator + { + color: #202020; + } + span.keyword + { + color: #840000; + } + span.name + { + color: black + } + span.type + { + font-weight: bold + } + span.type a:visited + { + color: #0F5300; + } + span.preprocessor + { + color: #404040 + } +/* end basic elements */ + +/* font style elements */ + .heading + { + font-weight: bold; + font-size: 125%; + } + .subtitle + { + font-size: 110% + } + .small-subtitle + { + font-size: 100% + } + .red + { + color:red; + } +/* end font style elements */ + +/* global settings*/ + .header, .footer + { + display: block; + clear: both; + overflow: hidden; + } +/* end global settings*/ + +/* header elements */ + .header .qtref + { + color: #735704; + font-weight: bold; + font-size: 130%; + } + + .header .content + { + margin-bottom: 0.5em + } + + .header .breadcrumb + { + font-size: 90%; + padding: 0.5em 0 0.5em 1em; + margin: 0; + background-color: #fafafa; + height: 1.35em; + border-bottom: 1px solid #d1d1d1; + } + + .header .breadcrumb ul + { + margin: 0; + padding: 0; + } + + .header .content + { + word-wrap: break-word; + } + + .header .breadcrumb ul li + { + float: left; + background: url(../images/breadcrumb.png) no-repeat 0 3px; + padding-left: 1.5em; + margin-left: 1.5em; + } + + .header .breadcrumb ul li.last + { + font-weight: normal; + } + + .header .breadcrumb ul li a + { + color: #735704; + } + + .header .breadcrumb ul li.first + { + background-image: none; + padding-left: 0; + margin-left: 0; + } + + .header .content ol li { + background: none; + margin-bottom: 1.0em; + margin-left: 1.2em; + padding-left: 0 + } + + .header .content li + { + background: url(../images/bullet_sq.png) no-repeat 0 5px; + margin-bottom: 1em; + padding-left: 1.2em; + } + +/* end header elements */ + +/* content elements */ + .content h1 + { + font-weight: bold; + font-size: 130% + } + + .content h2 + { + font-weight: bold; + font-size: 120%; + width: 100%; + } + .content h3 + { + font-weight: bold; + font-size: 110%; + width: 100%; + } + .content table p + { + margin: 0 + } + .content ul + { + padding-left: 2.5em; + } + .content li + { + padding-top: 0.25em; + padding-bottom: 0.25em; + } + .content ul img { + vertical-align: middle; + } + + .content a:visited + { + color: #4c0033; + text-decoration: none; + } + + .content a:visited:hover + { + color: #4c0033; + text-decoration: underline; + } + + a:hover + { + color: #4c0033; + text-decoration: underline; + } + descr p a + { + text-decoration: underline; + } + + .descr p a:visited + { + text-decoration: underline; + } + + .alphaChar{ + width:95%; + background-color:#F6F6F6; + border:1px solid #E6E6E6; + -moz-border-radius: 7px 7px 7px 7px; + border-radius: 7px 7px 7px 7px; + -webkit-border-radius: 7px 7px 7px 7px; + font-size:12pt; + padding-left:10px; + margin-top:10px; + margin-bottom:10px; + } + .flowList{ + /*vertical-align:top;*/ + /*margin:20px auto;*/ + + column-count:3; + -webkit-column-count:3; + -moz-column-count:3; +/* + column-width:100%; + -webkit-column-width:200px; + -col-column-width:200px; +*/ + column-gap:41px; + -webkit-column-gap:41px; + -moz-column-gap:41px; + + column-rule: 1px dashed #ccc; + -webkit-column-rule: 1px dashed #ccc; + -moz-column-rule: 1px dashed #ccc; + } + + .flowList dl{ + } + .flowList dd{ + /*display:inline-block;*/ + margin-left:10px; + min-width:250px; + line-height: 1.5; + min-width:100%; + min-height:15px; + } + + .flowList dd a{ + } + + .content .flowList p{ + padding:0px; + } + + .content .alignedsummary + { + margin: 15px; + } + + + .qmltype + { + text-align: center; + font-size: 120%; + } + .qmlreadonly + { + padding-left: 5px; + float: right; + color: #254117; + } + + .qmldefault + { + padding-left: 5px; + float: right; + color: red; + } + + .qmldoc + { + } + + .generic .alphaChar{ + margin-top:5px; + } + + .generic .odd .alphaChar{ + background-color: #F6F6F6; + } + + .generic .even .alphaChar{ + background-color: #FFFFFF; + } + + .memItemRight{ + padding: 0.25em 1.5em 0.25em 0; + } + .highlightedCode + { + margin: 1.0em; + } + .annotated td { + padding: 0.25em 0.5em 0.25em 0.5em; + } + + .toc + { + font-size: 80% + } + + .header .content .toc ul + { + padding-left: 0px; + } + + .content .toc h3 { + border-bottom: 0px; + margin-top: 0px; + } + + .content .toc h3 a:hover { + color: #735704; + text-decoration: none; + } + + .content .toc .level2 + { + margin-left: 1.5em; + } + + .content .toc .level3 + { + margin-left: 3.0em; + } + + .content ul li + { + background: url(../images/bullet_sq.png) no-repeat 0 0.7em; + padding-left: 1em + } + + .content .toc li + { + background: url(../images/bullet_dn.png) no-repeat 0 5px; + padding-left: 1em + } + + .relpage + { + -moz-border-radius: 7px 7px 7px 7px; + -webkit-border-radius: 7px 7px 7px 7px; + border-radius: 7px 7px 7px 7px; + border: 1px solid #DDDDDD; + padding: 25px 25px; + clear: both; + } + .relpage ul + { + float: none; + padding: 1.5em; + } + + h3.fn, span.fn + { + -moz-border-radius:7px 7px 7px 7px; + -webkit-border-radius:7px 7px 7px 7px; + border-radius:7px 7px 7px 7px; + background-color: #F6F6F6; + border-width: 1px; + border-style: solid; + border-color: #E6E6E6; + font-weight: bold; + word-spacing:3px; + padding:3px 5px; + } + + .functionIndex { + font-size:12pt; + word-spacing:10px; + margin-bottom:10px; + background-color: #F6F6F6; + border-width: 1px; + border-style: solid; + border-color: #E6E6E6; + -moz-border-radius: 7px 7px 7px 7px; + -webkit-border-radius: 7px 7px 7px 7px; + border-radius: 7px 7px 7px 7px; + width:100%; + } + + .centerAlign + { + text-align:center; + } + + .rightAlign + { + text-align:right; + } + + .leftAlign + { + text-align:left; + } + + .topAlign{ + vertical-align:top + } + + .functionIndex a{ + display:inline-block; + } + +/* end content elements */ +/* footer elements */ + + .footer + { + color: #393735; + font-size: 0.75em; + text-align: center; + padding-top: 1.5em; + padding-bottom: 1em; + background-color: #E6E7E8; + margin: 0; + } + .footer p + { + margin: 0.25em + } + .small + { + font-size: 0.5em; + } +/* end footer elements */ + + .item { + float: left; + position: relative; + width: 100%; + overflow: hidden; + } + + + .item .primary { + margin-right: 220px; + position: relative; + } + + .item hr { + margin-left: -220px; + } + + .item .secondary { + float: right; + width: 200px; + position: relative; + } + + .item .cols { + clear: both; + display: block; + } + + .item .cols .col { + float: left; + margin-left: 1.5%; + } + + .item .cols .col.first { + margin-left: 0; + } + + .item .cols.two .col { + width: 45%; + } + + .item .box { + margin: 0 0 10px 0; + } + + .item .box h3 { + margin: 0 0 10px 0; + } + + .cols.unclear { + clear:none; + } +} + +/* end of screen media */ + +/* start of print media */ + +@media print +{ + input, textarea, .header, .footer, .toolbar, .feedback, .wrapper .hd, .wrapper .bd .sidebar, .wrapper .ft, #feedbackBox, #blurpage, .toc, .breadcrumb, .toolbar, .floatingResult + { + display: none; + background: none; + } + .content + { + background: none; + display: block; + width: 100%; margin: 0; float: none; + } +} +/* end of print media */ diff --git a/doc/config/transfer-engine-ditaxml.qdocconf b/doc/config/transfer-engine-ditaxml.qdocconf new file mode 100644 index 0000000..b207c51 --- /dev/null +++ b/doc/config/transfer-engine-ditaxml.qdocconf @@ -0,0 +1,13 @@ +include(transfer-engine-project.qdocconf) + +outputdir = ../ditaxml +outputformats = DITAXML + +generateindex = true +url = . + +macro.beginfloatleft.HTML = " " +macro.beginfloatright.HTML = " " +macro.endfloat.HTML = " " +macro.clearfloat.HTML = " " +macro.emptyspan.DITAXML = " " diff --git a/doc/config/transfer-engine-project.qdocconf b/doc/config/transfer-engine-project.qdocconf new file mode 100644 index 0000000..f021937 --- /dev/null +++ b/doc/config/transfer-engine-project.qdocconf @@ -0,0 +1,62 @@ +include(compat.qdocconf) +include(macros.qdocconf) +include(qt-cpp-ignore.qdocconf) +include(qt-defines.qdocconf) + +indexes = ../src/qt.index + +language = Cpp + +sourceencoding = UTF-8 +outputencoding = UTF-8 +naturallanguage = en_US + +project = Nemo TransferEngine +description = Nemo TransferEngine Library Reference Documentation +versionsym = +version = 1.0 +url = + +sources.fileextensions = "*.cpp *.qdoc *.mm *.qml" +headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx" +examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml" +examples.imageextensions = "*.png *.jpeg *.jpg *.gif *.mng" + +# don't include ../../components/*.qml in sourcedirs, that causes qdoc3 to parse the +# .qml files, not find any docs, and conclude they are internal +sourcedirs = ../../src ../../lib ../src +headerdirs = ../../src ../../lib + +#excludedirs = + +#exampledirs = ../../examples + +imagedirs = images \ + ../src/images + +outputdir = ../html +tagfile = ../html/transfer-engine.tags +base = file:../html + +outputprefixes = QML +outputprefixes.QML = qml-transfer-engine- + +qhp.projects = TransferEngine + +qhp.TransferEngine.file = transferengine.qhp +qhp.TransferEngine.namespace = Transfer.Engine.100 +qhp.TransferEngine.virtualFolder = transferengine +qhp.TransferEngine.indexTitle = Nemo Transfer Engine Reference Documentation +qhp.TransferEngine.indexRoot = + +qhp.TransferEngine.filterAttributes = transferengine 1.0.0 +qhp.TransferEngine.customFilters.TransferEngine.name = Nemo TransferEngine 1.0.0 +qhp.TransferEngine.customFilters.TransferEngine.filterAttributes = transferengine 1.0.0 +#qhp.TransferEngine.subprojects.examples.title = Examples +#qhp.TransferEngine.subprojects.examples.indexTitle = Nemo Transfer Engine Examples +#qhp.TransferEngine.subprojects.examples.selectors = fake:example +#qhp.TransferEngine.subprojects.examples.sortPages = true +#qhp.TransferEngine.subprojects.tutorials.title = Tutorials +#qhp.TransferEngine.subprojects.tutorials.indexTitle = Nemo TransferEngine Tutorials +#qhp.TransferEngine.subprojects.tutorials.selectors = fake:tutorial +#qhp.TransferEngine.subprojects.tutorials.sortPages = true diff --git a/doc/config/transfer-engine.qdocconf b/doc/config/transfer-engine.qdocconf new file mode 100644 index 0000000..76f8bcb --- /dev/null +++ b/doc/config/transfer-engine.qdocconf @@ -0,0 +1,2 @@ +include(transfer-engine-project.qdocconf) +include(qt-html-templates.qdocconf) diff --git a/doc/doc.pri b/doc/doc.pri new file mode 100644 index 0000000..dca6f96 --- /dev/null +++ b/doc/doc.pri @@ -0,0 +1,15 @@ +QDOC = qdoc3 +QHELPGENERATOR = qhelpgenerator +QDOCCONF = doc/config/transfer-engine-project.qdocconf +QHELPFILE = doc/html/transferengine.qhp +QCHFILE = doc/html/transferengine.qch + +docs.commands = ($$QDOC $$QDOCCONF) && \ + ($$QHELPGENERATOR $$QHELPFILE -o $$QCHFILE) + +QMAKE_EXTRA_TARGETS += docs + +doc.files = doc/html/* +doc.path = /usr/share/doc/nemo-transfer-engine +INSTALLS += doc + diff --git a/doc/html/callbackinterface-members.html b/doc/html/callbackinterface-members.html new file mode 100644 index 0000000..1c067b9 --- /dev/null +++ b/doc/html/callbackinterface-members.html @@ -0,0 +1,18 @@ + + + + + + + Nemo TransferEngine 1.0: List of All Members for CallbackInterface +
  • Modules
  • +
  • CallbackInterface
  • +

    List of All Members for CallbackInterface

    +

    This is the complete list of members for CallbackInterface, including inherited members.

    + + + diff --git a/doc/html/callbackinterface.html b/doc/html/callbackinterface.html new file mode 100644 index 0000000..2efaa67 --- /dev/null +++ b/doc/html/callbackinterface.html @@ -0,0 +1,63 @@ + + + + + + + Nemo TransferEngine 1.0: CallbackInterface Class Reference +
  • Modules
  • +
  • CallbackInterface
  • +
    +

    Contents

    + +
    +

    CallbackInterface Class Reference

    + +

    The CallbackInterface class is a convenience class to wrap DBus callback infromation for TransferEngineClient API. More...

    + +
     #include <CallbackInterface>
    + +

    Public Functions

    + + + + +
    CallbackInterface ()
    CallbackInterface ( const QString & server, const QString & path, const QString & interface, const QString & cancelMethod, const QString & restartMethod )
    ~CallbackInterface ()
    + + +
    +

    Detailed Description

    +

    The CallbackInterface class is a convenience class to wrap DBus callback infromation for TransferEngineClient API.

    +

    This class should be used with TransferEngineClient API.

    +

    NOTE: If creating an instance of this class to the heap, the caller is responsible of freeing the allocated memory.

    +
    +

    See also TransferEngineClient::createSyncEvent() and TransferEngineClient::createDownloadEvent().

    + +
    +

    Member Function Documentation

    + +

    CallbackInterface::CallbackInterface ()

    +

    Construct an empty CallbackInterface. This can be used if client doesn't want to provide callback interface to the Sync or Download events.

    + + +

    CallbackInterface::CallbackInterface ( const QString & server, const QString & path, const QString & interface, const QString & cancelMethod, const QString & restartMethod )

    +

    Construct CallbackInterface instance to provide callback information to the TransferEngineClient. Setup arguments as:

    + + + +

    CallbackInterface::~CallbackInterface ()

    + +
    + + diff --git a/doc/html/dbmanager-members.html b/doc/html/dbmanager-members.html new file mode 100644 index 0000000..72be390 --- /dev/null +++ b/doc/html/dbmanager-members.html @@ -0,0 +1,30 @@ + + + + + + + Nemo TransferEngine 1.0: List of All Members for DbManager +
  • Modules
  • +
  • DbManager
  • +

    List of All Members for DbManager

    +

    This is the complete list of members for DbManager, including inherited members.

    + + + diff --git a/doc/html/dbmanager.html b/doc/html/dbmanager.html new file mode 100644 index 0000000..2ad540e --- /dev/null +++ b/doc/html/dbmanager.html @@ -0,0 +1,150 @@ + + + + + + + Nemo TransferEngine 1.0: DbManager Class Reference +
  • Modules
  • +
  • DbManager
  • +
    +

    Contents

    + +
    +

    DbManager Class Reference

    + +

    The DbManager class is a singleton class to read and write transfers database. More...

    + +
     #include <DbManager>
    + +

    Public Functions

    + + + + + + + + + + + + + + + +
    ~DbManager ()
    QStringList callback ( int key ) const
    bool callbackMethods ( int key, QString & cancelMethod, QString & restartMethod ) const
    bool clearTransfers ()
    int createCallbackEntry ( int key, const QString & service, const QString & path, const QString & interface, const QString & cancelMethod, const QString & restartMethod )
    int createMetadataEntry ( int key, const QString & title, const QString & description )
    int createTransferEntry ( MediaItem * mediaItem )
    MediaItem * mediaItem ( int key ) const
    bool removeTransfer ( int key )
    TransferEngineData::TransferStatus transferStatus ( int key ) const
    TransferEngineData::TransferType transferType ( int key ) const
    QList<TransferDBRecord> transfers () const
    bool updateProgress ( int key, qreal progress )
    bool updateTransferStatus ( int key, TransferEngineData::TransferStatus status )
    + +

    Static Public Members

    + + +
    DbManager * instance ()
    + + +
    +

    Detailed Description

    +

    The DbManager class is a singleton class to read and write transfers database.

    +

    DbManager class takes care of reading and writing transfer database used by Nemo Transfer Engine. It's a singleton class and it can be instantiated using DbManager::instance() method.

    +
    + +
    +

    Member Function Documentation

    + +

    DbManager::~DbManager ()

    +

    Destructor.

    + + +

    QStringList DbManager::callback ( int key ) const

    +

    Get a DBus callback interface and method for the transfer with key. If there is no callback for the key then an empty QStringList is returned.

    +

    In a case there is a DBus callback, then QStringList contains the following items:

    + + + +

    bool DbManager::callbackMethods ( int key, QString & cancelMethod, QString & restartMethod ) const

    +

    Get the callback method names for the transfer with key. The method names are set to the output arguments cancelMethod and restartMethod.

    +

    This method returns true on success, false on failure.

    + + +

    bool DbManager::clearTransfers ()

    +

    Clear all finished, canceled or failed transfers from the database.

    +

    This method returns true on success, false on failure.

    + + +

    int DbManager::createCallbackEntry ( int key, const QString & service, const QString & path, const QString & interface, const QString & cancelMethod, const QString & restartMethod )

    +

    Create a callback entry to the callback table for the existing transfer with a key.

    +

    The callback is a dbus interface so it must contain the following attributes:

    + +

    This method returns a key of the created callback record in a callback table or -1 on failure.

    +

    NOTE: Deleting the record from the transfer which has a key, also deletes related callback entry.

    + + +

    int DbManager::createMetadataEntry ( int key, const QString & title, const QString & description )

    +

    Create a metadata entry for the existing transfer with key. Metadata can contain only title and/or \description.

    +

    Metadata entry will be created to the metadata table. Argument key must point to the existing entry in transfers table.

    +

    This method returns a key of the created record in metadata table or -1 on failure.

    +

    NOTE: Deleting the record from the transfer which has a key, also deletes related metadata entry.

    + + +

    int DbManager::createTransferEntry ( MediaItem * mediaItem )

    +

    Create a transfer entry to the transfers table bsaed on mediaItem content.

    +

    MediaItem instance contains all the required information for the single Upload, Download or a Sync item. Based on this information, DbManager creates a record to the transfers table, but also to the callback and metadata tables if these are defined.

    +

    This method returns a key of the created transfer or -1 on failure.

    +

    See also MediaItem.

    + + +

    DbManager * DbManager::instance () [static]

    +

    Return a singleton instance of this DbManager. Note that caller is NOT responsible of deleting the instance. It will be deleted automatically when application stack is cleaned.

    + + +

    MediaItem * DbManager::mediaItem ( int key ) const

    +

    Returns a MediaItem instance from the transfer data with a key.

    + + +

    bool DbManager::removeTransfer ( int key )

    +

    Remove an existing transfer with a key from the transfers table. If this transfer has metadata or callback defined, they will be removed too.

    +

    This method returns true on success, false on failure.

    + + +

    TransferEngineData::TransferStatus DbManager::transferStatus ( int key ) const

    +

    Returns the transfer status of the transfer with key. In a case of error the TransferEngineData::Unknown is returned.

    + + +

    TransferEngineData::TransferType DbManager::transferType ( int key ) const

    +

    Returns the transfer type e.g. Sync, Download or Upload of the transfer with a key.

    +

    If there is no transfer record with key or error occurs, this method returns TransferEngineData::Undefined.

    + + +

    QList<TransferDBRecord> DbManager::transfers () const

    +

    Returns all the transfers from the database. This method doesn't fetch all the fields from all the tables, instead it returns what is required to fill fields in TransferDBRecord class.

    + + +

    bool DbManager::updateProgress ( int key, qreal progress )

    +

    Update a transfer progress of the existing transfer with key.

    +

    This method returns true on success, false on failure.

    + + +

    bool DbManager::updateTransferStatus ( int key, TransferEngineData::TransferStatus status )

    +

    Update a transfer status of the existing transfer with key. Changing the status updates the timestamp too.

    +

    This method returns true on success, false on failure.

    + +
    + + diff --git a/doc/html/imageoperation-members.html b/doc/html/imageoperation-members.html new file mode 100644 index 0000000..5addf06 --- /dev/null +++ b/doc/html/imageoperation-members.html @@ -0,0 +1,18 @@ + + + + + + + Nemo TransferEngine 1.0: List of All Members for ImageOperation +
  • Modules
  • +
  • ImageOperation
  • +

    List of All Members for ImageOperation

    +

    This is the complete list of members for ImageOperation, including inherited members.

    + + + diff --git a/doc/html/imageoperation.html b/doc/html/imageoperation.html new file mode 100644 index 0000000..abcce3a --- /dev/null +++ b/doc/html/imageoperation.html @@ -0,0 +1,66 @@ + + + + + + + Nemo TransferEngine 1.0: ImageOperation Class Reference +
  • Modules
  • +
  • ImageOperation
  • +
    +

    Contents

    + +
    +

    ImageOperation Class Reference

    + +

    The ImageOperation class is a helper class to manipulate images. More...

    + +
     #include <ImageOperation>
    + +

    Static Public Members

    + + + + +
    QString removeImageMetadata ( const QString & sourceFile )
    QString scaleImage ( const QString & sourceFile, qreal scaleFactor, const QString & targetFile = QString() )
    QString tempFilePath ( const QString & sourceFile )
    + + +
    +

    Detailed Description

    +

    The ImageOperation class is a helper class to manipulate images.

    +

    This class is meant to be used by share plugins. It can be used for:

    + +
    + +
    +

    Member Function Documentation

    + +

    QString ImageOperation::removeImageMetadata ( const QString & sourceFile ) [static]

    +

    Helper method to remove metadata from jpeg files. Only author and location related metadata will be removed. sourceFile is the path to the original file.

    +

    Returns a path to the copy of the image with metadata removed.

    + + +

    QString ImageOperation::scaleImage ( const QString & sourceFile, qreal scaleFactor, const QString & targetFile = QString() ) [static]

    +

    Scale image sourceFile using scaleFactor. The scaled image is stored to the targetFile or if targetFile is not given, then a temporary file is created for saving.

    +

    The scaleFactor argument must be > 0. This function returns path to the scaled image. Note that if user doesn't specify targetFile the scaled image is stored under temp directory. Nothing guarantees that created file will remain in that diretory forewer so the caller is reponsible of copying file for more permanent storing.

    +

    Returns a path to the scaled image.

    +

    It is also recommended that if the caller doesn't use the scaled file, which is stored to the temp directory later, the caller should remove the file.

    + + +

    QString ImageOperation::tempFilePath ( const QString & sourceFile ) [static]

    +

    Creates a temporary file from the sourceFile. This function uses sourceFile as a template to create a temp file. Temporary file will be e.g:

    +

    Source file: "/home/nemo/Pictures/img_001.jpg" Temporary file: "/var/tmp/img_001_0.jpg"

    +

    Note that it's caller's responsibility to remove created temp file.

    + +
    + + diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 0000000..cd5125c --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,42 @@ + + + + + + + Nemo TransferEngine 1.0: Nemo Transfer Engine +
  • Nemo Transfer Engine
  • +

    +

    Nemo Transfer Engine

    + + +
    +

    The Nemo Transfer Engine is a daemon process which takes care of tracking sharing, sync and downloads. In addition to just tracking those operations, it provides an API to create new share plugins and different functionality related these operations.The Nemo Transfer Engine doesn't provide any UI components, but the plugin interface expects sharing UIs to be written as QML.

    +

    The Nemo Transfer Engine can be understood as a front end to the database which contain all the information about sharing, syncs and downloads. For syncs and downloads it acts only as storage manager so clients can use Nemo Transfer Engine client API to create and update sync and download events. For sharing, Nemo Transfer Engine provides own API and supports share plugins.

    +

    See TransferEngine DbManager

    + +

    Nemo Transfer Engine API

    +

    The API can be divided in two different parts: the share plugin API and the client API.

    + +

    Share Plugin API

    +

    Share plugin is a Qt plugin, which must be implemented using C++ interfaces defined by Nemo Transfer Engine. The plugins must be installed to the specific location where Nemo Transfer Engine loads them. The actual share functionality implementation depends on the client e.g. if it's HW specific like NFC or online service such as Facebook. Each plugin must implement or use the following interface:

    + + +

    Client API

    +

    Client API can also be divided in two sections: full features DBus API and TransferEngineClient Interface. The first one supports all the features Nemo Transfer Engine provides and makes possible to implement for example Transfer UI and client side sharing interface on top of it. The TransferEngineClient is meant to be used by clients who want to inform Nemo Transfer Engine of ongoing Sync or Downloads.

    + +
    + + + + diff --git a/doc/html/nemo-transferengine.index b/doc/html/nemo-transferengine.index new file mode 100644 index 0000000..c28805f --- /dev/null +++ b/doc/html/nemo-transferengine.index @@ -0,0 +1,277 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/html/nemo-transferengine.pageindex b/doc/html/nemo-transferengine.pageindex new file mode 100644 index 0000000..89692e7 --- /dev/null +++ b/doc/html/nemo-transferengine.pageindex @@ -0,0 +1,609 @@ + + + + ImageOperation class reference + ImageOperation Class Reference + imageoperation.html + APIPage + + + tempFilePath function ImageOperation + tempFilePath Function Reference + imageoperation.html#tempFilePath + APIPage + + + removeImageMetadata function ImageOperation + removeImageMetadata Function Reference + imageoperation.html#removeImageMetadata + APIPage + + + scaleImage function ImageOperation + scaleImage Function Reference + imageoperation.html#scaleImage + APIPage + + + CallbackInterface class reference + CallbackInterface Class Reference + callbackinterface.html + APIPage + + + CallbackInterface function CallbackInterface + CallbackInterface Function Reference + callbackinterface.html#CallbackInterface + APIPage + + + CallbackInterface function CallbackInterface + CallbackInterface Function Reference + callbackinterface.html#CallbackInterface + APIPage + + + ~CallbackInterface function CallbackInterface + ~CallbackInterface Function Reference + callbackinterface.html#~CallbackInterface + APIPage + + + TransferEngineClient class reference + TransferEngineClient Class Reference + transferengineclient.html + APIPage + + + Status enum type TransferEngineClient + Status Enum Reference + transferengineclient.html#Status-enum + APIPage + + + TransferEngineClient function TransferEngineClient + TransferEngineClient Function Reference + transferengineclient.html#TransferEngineClient + APIPage + + + ~TransferEngineClient function TransferEngineClient + ~TransferEngineClient Function Reference + transferengineclient.html#~TransferEngineClient + APIPage + + + createDownloadEvent function TransferEngineClient + createDownloadEvent Function Reference + transferengineclient.html#createDownloadEvent + APIPage + + + createSyncEvent function TransferEngineClient + createSyncEvent Function Reference + transferengineclient.html#createSyncEvent + APIPage + + + startTransfer function TransferEngineClient + startTransfer Function Reference + transferengineclient.html#startTransfer + APIPage + + + updateTransferProgress function TransferEngineClient + updateTransferProgress Function Reference + transferengineclient.html#updateTransferProgress + APIPage + + + finishTransfer function TransferEngineClient + finishTransfer Function Reference + transferengineclient.html#finishTransfer + APIPage + + + DbManager class reference + DbManager Class Reference + dbmanager.html + APIPage + + + instance function DbManager + instance Function Reference + dbmanager.html#instance + APIPage + + + ~DbManager function DbManager + ~DbManager Function Reference + dbmanager.html#~DbManager + APIPage + + + createMetadataEntry function DbManager + createMetadataEntry Function Reference + dbmanager.html#createMetadataEntry + APIPage + + + callback function DbManager + callback Function Reference + dbmanager.html#callback + APIPage + + + createCallbackEntry function DbManager + createCallbackEntry Function Reference + dbmanager.html#createCallbackEntry + APIPage + + + createTransferEntry function DbManager + createTransferEntry Function Reference + dbmanager.html#createTransferEntry + APIPage + + + updateTransferStatus function DbManager + updateTransferStatus Function Reference + dbmanager.html#updateTransferStatus + APIPage + + + updateProgress function DbManager + updateProgress Function Reference + dbmanager.html#updateProgress + APIPage + + + removeTransfer function DbManager + removeTransfer Function Reference + dbmanager.html#removeTransfer + APIPage + + + clearTransfers function DbManager + clearTransfers Function Reference + dbmanager.html#clearTransfers + APIPage + + + transfers function DbManager + transfers Function Reference + dbmanager.html#transfers + APIPage + + + transferType function DbManager + transferType Function Reference + dbmanager.html#transferType + APIPage + + + transferStatus function DbManager + transferStatus Function Reference + dbmanager.html#transferStatus + APIPage + + + callbackMethods function DbManager + callbackMethods Function Reference + dbmanager.html#callbackMethods + APIPage + + + mediaItem function DbManager + mediaItem Function Reference + dbmanager.html#mediaItem + APIPage + + + TransferEngine class reference + TransferEngine Class Reference + transferengine.html + APIPage + + + TransferEngine function TransferEngine + TransferEngine Function Reference + transferengine.html#TransferEngine + APIPage + + + ~TransferEngine function TransferEngine + ~TransferEngine Function Reference + transferengine.html#~TransferEngine + APIPage + + + uploadMediaItem function TransferEngine + uploadMediaItem Function Reference + transferengine.html#uploadMediaItem + APIPage + + + uploadMediaItemContent function TransferEngine + uploadMediaItemContent Function Reference + transferengine.html#uploadMediaItemContent + APIPage + + + createDownload function TransferEngine + createDownload Function Reference + transferengine.html#createDownload + APIPage + + + createSync function TransferEngine + createSync Function Reference + transferengine.html#createSync + APIPage + + + startTransfer function TransferEngine + startTransfer Function Reference + transferengine.html#startTransfer + APIPage + + + restartTransfer function TransferEngine + restartTransfer Function Reference + transferengine.html#restartTransfer + APIPage + + + finishTransfer function TransferEngine + finishTransfer Function Reference + transferengine.html#finishTransfer + APIPage + + + updateTransferProgress function TransferEngine + updateTransferProgress Function Reference + transferengine.html#updateTransferProgress + APIPage + + + transfers function TransferEngine + transfers Function Reference + transferengine.html#transfers + APIPage + + + transferMethods function TransferEngine + transferMethods Function Reference + transferengine.html#transferMethods + APIPage + + + clearTransfers function TransferEngine + clearTransfers Function Reference + transferengine.html#clearTransfers + APIPage + + + cancelTransfer function TransferEngine + cancelTransfer Function Reference + transferengine.html#cancelTransfer + APIPage + + + enableNotifications function TransferEngine + enableNotifications Function Reference + transferengine.html#enableNotifications + APIPage + + + notificationsEnabled function TransferEngine + notificationsEnabled Function Reference + transferengine.html#notificationsEnabled + APIPage + + + progressChanged function TransferEngine + progressChanged Function Reference + transferengine.html#progressChanged + APIPage + + + statusChanged function TransferEngine + statusChanged Function Reference + transferengine.html#statusChanged + APIPage + + + transferMethodListChanged function TransferEngine + transferMethodListChanged Function Reference + transferengine.html#transferMethodListChanged + APIPage + + + transfersChanged function TransferEngine + transfersChanged Function Reference + transferengine.html#transfersChanged + APIPage + + + TransferMethodInfo class reference + TransferMethodInfo Class Reference + transfermethodinfo.html + APIPage + + + TransferMethodInfoField enum type TransferMethodInfo + TransferMethodInfoField Enum Reference + transfermethodinfo.html#TransferMethodInfoField-enum + APIPage + + + TransferMethodInfo function TransferMethodInfo + TransferMethodInfo Function Reference + transfermethodinfo.html#TransferMethodInfo + APIPage + + + operator= function TransferMethodInfo + operator= Function Reference + transfermethodinfo.html#operator= + APIPage + + + TransferMethodInfo function TransferMethodInfo + TransferMethodInfo Function Reference + transfermethodinfo.html#TransferMethodInfo + APIPage + + + ~TransferMethodInfo function TransferMethodInfo + ~TransferMethodInfo Function Reference + transfermethodinfo.html#~TransferMethodInfo + APIPage + + + registerType function TransferMethodInfo + registerType Function Reference + transfermethodinfo.html#registerType + APIPage + + + value function TransferMethodInfo + value Function Reference + transfermethodinfo.html#value + APIPage + + + displayName TransferMethodInfo + displayName + transfermethodinfo.html + APIPage + + + userName TransferMethodInfo + userName + transfermethodinfo.html + APIPage + + + methodId TransferMethodInfo + methodId + transfermethodinfo.html + APIPage + + + shareUIPath TransferMethodInfo + shareUIPath + transfermethodinfo.html + APIPage + + + capabilitities TransferMethodInfo + capabilitities + transfermethodinfo.html + APIPage + + + accountId TransferMethodInfo + accountId + transfermethodinfo.html + APIPage + + + TransferPluginInterface class reference + TransferPluginInterface Class Reference + transferplugininterface.html + APIPage + + + transferObject function TransferPluginInterface + transferObject Function Reference + transferplugininterface.html#transferObject + APIPage + + + infoObject function TransferPluginInterface + infoObject Function Reference + transferplugininterface.html#infoObject + APIPage + + + pluginId function TransferPluginInterface + pluginId Function Reference + transferplugininterface.html#pluginId + APIPage + + + enabled function TransferPluginInterface + enabled Function Reference + transferplugininterface.html#enabled + APIPage + + + TransferDBRecord class reference + TransferDBRecord Class Reference + transferdbrecord.html + APIPage + + + TransferDBRecordField enum type TransferDBRecord + TransferDBRecordField Enum Reference + transferdbrecord.html#TransferDBRecordField-enum + APIPage + + + TransferDBRecord function TransferDBRecord + TransferDBRecord Function Reference + transferdbrecord.html#TransferDBRecord + APIPage + + + operator= function TransferDBRecord + operator= Function Reference + transferdbrecord.html#operator= + APIPage + + + TransferDBRecord function TransferDBRecord + TransferDBRecord Function Reference + transferdbrecord.html#TransferDBRecord + APIPage + + + ~TransferDBRecord function TransferDBRecord + ~TransferDBRecord Function Reference + transferdbrecord.html#~TransferDBRecord + APIPage + + + registerType function TransferDBRecord + registerType Function Reference + transferdbrecord.html#registerType + APIPage + + + value function TransferDBRecord + value Function Reference + transferdbrecord.html#value + APIPage + + + transfer_id TransferDBRecord + transfer_id + transferdbrecord.html + APIPage + + + transfer_type TransferDBRecord + transfer_type + transferdbrecord.html + APIPage + + + status TransferDBRecord + status + transferdbrecord.html + APIPage + + + size TransferDBRecord + size + transferdbrecord.html + APIPage + + + progress TransferDBRecord + progress + transferdbrecord.html + APIPage + + + plugin_id TransferDBRecord + plugin_id + transferdbrecord.html + APIPage + + + url TransferDBRecord + url + transferdbrecord.html + APIPage + + + timestamp TransferDBRecord + timestamp + transferdbrecord.html + APIPage + + + display_name TransferDBRecord + display_name + transferdbrecord.html + APIPage + + + resource_name TransferDBRecord + resource_name + transferdbrecord.html + APIPage + + + mime_type TransferDBRecord + mime_type + transferdbrecord.html + APIPage + + + service_icon TransferDBRecord + service_icon + transferdbrecord.html + APIPage + + + application_icon TransferDBRecord + application_icon + transferdbrecord.html + APIPage + + + thumbnail_icon TransferDBRecord + thumbnail_icon + transferdbrecord.html + APIPage + + + cancel_supported TransferDBRecord + cancel_supported + transferdbrecord.html + APIPage + + + restart_supported TransferDBRecord + restart_supported + transferdbrecord.html + APIPage + + + Nemo Transfer Engine + Nemo Transfer Engine + index.html + Article + + + Nemo Transfer Engine Nemo Transfer Engine API + Nemo Transfer Engine API + index.html#nemo-transfer-engine-api + Article + + + Nemo Transfer Engine Share Plugin API + Share Plugin API + index.html#share-plugin-api + Article + + + Nemo Transfer Engine Client API + Client API + index.html#client-api + Article + + diff --git a/doc/html/transfer-engine.tags b/doc/html/transfer-engine.tags new file mode 100644 index 0000000..d1358f0 --- /dev/null +++ b/doc/html/transfer-engine.tags @@ -0,0 +1,598 @@ + + + + ImageOperation + imageoperation.html + + QString + tempFilePath + imageoperation.html + tempFilePath + (const QString & sourceFile) + + + QString + removeImageMetadata + imageoperation.html + removeImageMetadata + (const QString & sourceFile) + + + QString + scaleImage + imageoperation.html + scaleImage + (const QString & sourceFile, qreal scaleFactor, const QString & targetFile) + + + + CallbackInterface + callbackinterface.html + + + CallbackInterface + callbackinterface.html + CallbackInterface + () + + + + CallbackInterface + callbackinterface.html + CallbackInterface-2 + (const QString & server, const QString & path, const QString & interface, const QString & cancelMethod, const QString & restartMethod) + + + + ~CallbackInterface + callbackinterface.html + dtor.CallbackInterface + () + + + + TransferEngineClient + transferengineclient.html + + Status + Status-enum + + + + Status-enum + + + + Status-enum + + + + Status-enum + + + + + TransferEngineClient + transferengineclient.html + TransferEngineClient + (QObject * parent) + + + + ~TransferEngineClient + transferengineclient.html + dtor.TransferEngineClient + () + + + int + createDownloadEvent + transferengineclient.html + createDownloadEvent + (const QString & displayName, const QUrl & applicationIcon, const QUrl & serviceIcon, const QUrl & url, const QString & mimeType, qlonglong expectedFileSize, const CallbackInterface & callback) + + + int + createSyncEvent + transferengineclient.html + createSyncEvent + (const QString & displayName, const QUrl & applicationIcon, const QUrl & serviceIcon, const CallbackInterface & callback) + + + void + startTransfer + transferengineclient.html + startTransfer + (int transferId) + + + void + updateTransferProgress + transferengineclient.html + updateTransferProgress + (int transferId, qreal progress) + + + void + finishTransfer + transferengineclient.html + finishTransfer + (int transferId, Status status, const QString & reason) + + + + DbManager + dbmanager.html + + DbManager * + instance + dbmanager.html + instance + () + + + + ~DbManager + dbmanager.html + dtor.DbManager + () + + + int + createMetadataEntry + dbmanager.html + createMetadataEntry + (int key, const QString & title, const QString & description) + + + QStringList + callback + dbmanager.html + callback + (int key) const + + + int + createCallbackEntry + dbmanager.html + createCallbackEntry + (int key, const QString & service, const QString & path, const QString & interface, const QString & cancelMethod, const QString & restartMethod) + + + int + createTransferEntry + dbmanager.html + createTransferEntry + (MediaItem * mediaItem) + + + bool + updateTransferStatus + dbmanager.html + updateTransferStatus + (int key, TransferEngineData::TransferStatus status) + + + bool + updateProgress + dbmanager.html + updateProgress + (int key, qreal progress) + + + bool + removeTransfer + dbmanager.html + removeTransfer + (int key) + + + bool + clearTransfers + dbmanager.html + clearTransfers + () + + + QList<TransferDBRecord> + transfers + dbmanager.html + transfers + () const + + + TransferEngineData::TransferType + transferType + dbmanager.html + transferType + (int key) const + + + TransferEngineData::TransferStatus + transferStatus + dbmanager.html + transferStatus + (int key) const + + + bool + callbackMethods + dbmanager.html + callbackMethods + (int key, QString & cancelMethod, QString & restartMethod) const + + + MediaItem * + mediaItem + dbmanager.html + mediaItem + (int key) const + + + + TransferEngine + transferengine.html + + + TransferEngine + transferengine.html + TransferEngine + (QObject * parent) + + + + ~TransferEngine + transferengine.html + dtor.TransferEngine + () + + + int + uploadMediaItem + transferengine.html + uploadMediaItem + (const QString & source, const QString & serviceId, const QString & mimeType, bool metadataStripped, const QVariantMap & userData) + + + int + uploadMediaItemContent + transferengine.html + uploadMediaItemContent + (const QVariantMap & content, const QString & serviceId, const QVariantMap & userData) + + + int + createDownload + transferengine.html + createDownload + (const QString & displayName, const QString & applicationIcon, const QString & serviceIcon, const QString & filePath, const QString & mimeType, qlonglong expectedFileSize, const QStringList & callback, const QString & cancelMethod, const QString & restartMethod) + + + int + createSync + transferengine.html + createSync + (const QString & displayName, const QString & applicationIcon, const QString & serviceIcon, const QStringList & callback, const QString & cancelMethod, const QString & restartMethod) + + + void + startTransfer + transferengine.html + startTransfer + (int transferId) + + + void + restartTransfer + transferengine.html + restartTransfer + (int transferId) + + + void + finishTransfer + transferengine.html + finishTransfer + (int transferId, int status, const QString & reason) + + + void + updateTransferProgress + transferengine.html + updateTransferProgress + (int transferId, double progress) + + + QList<TransferDBRecord> + transfers + transferengine.html + transfers + () + + + QList<TransferMethodInfo> + transferMethods + transferengine.html + transferMethods + () + + + void + clearTransfers + transferengine.html + clearTransfers + () + + + void + cancelTransfer + transferengine.html + cancelTransfer + (int transferId) + + + void + enableNotifications + transferengine.html + enableNotifications + (bool enable) + + + bool + notificationsEnabled + transferengine.html + notificationsEnabled + () + + + void + progressChanged + transferengine.html + progressChanged + (int transferId, double progress) + + + void + statusChanged + transferengine.html + statusChanged + (int transferId, int status) + + + void + transferMethodListChanged + transferengine.html + transferMethodListChanged + () + + + void + transfersChanged + transferengine.html + transfersChanged + () + + + + TransferMethodInfo + transfermethodinfo.html + + TransferMethodInfoField + TransferMethodInfoField-enum + + + + TransferMethodInfoField-enum + + + + TransferMethodInfoField-enum + + + + TransferMethodInfoField-enum + + + + TransferMethodInfoField-enum + + + + TransferMethodInfoField-enum + + + + TransferMethodInfoField-enum + + + + + TransferMethodInfo + transfermethodinfo.html + TransferMethodInfo + () + + + TransferMethodInfo & + operator= + transfermethodinfo.html + operator= + (const TransferMethodInfo & other) + + + + TransferMethodInfo + transfermethodinfo.html + TransferMethodInfo-2 + (const TransferMethodInfo & other) + + + + ~TransferMethodInfo + transfermethodinfo.html + dtor.TransferMethodInfo + () + + + void + registerType + transfermethodinfo.html + registerType + () + + + QVariant + value + transfermethodinfo.html + value + (int index) const + + + + TransferPluginInterface + transferplugininterface.html + + virtual MediaTransferInterface * + transferObject + transferplugininterface.html + transferObject + () = 0 + + + virtual TransferPluginInfo * + infoObject + transferplugininterface.html + infoObject + () = 0 + + + virtual QString + pluginId + transferplugininterface.html + pluginId + () const = 0 + + + virtual bool + enabled + transferplugininterface.html + enabled + () const = 0 + + + + TransferDBRecord + transferdbrecord.html + + TransferDBRecordField + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + TransferDBRecordField-enum + + + + + TransferDBRecord + transferdbrecord.html + TransferDBRecord + () + + + TransferDBRecord & + operator= + transferdbrecord.html + operator= + (const TransferDBRecord & other) + + + + TransferDBRecord + transferdbrecord.html + TransferDBRecord-2 + (const TransferDBRecord & other) + + + + ~TransferDBRecord + transferdbrecord.html + dtor.TransferDBRecord + () + + + void + registerType + transferdbrecord.html + registerType + () + + + QVariant + value + transferdbrecord.html + value + (int index) const + + + diff --git a/doc/html/transferdbrecord-members.html b/doc/html/transferdbrecord-members.html new file mode 100644 index 0000000..64b12f1 --- /dev/null +++ b/doc/html/transferdbrecord-members.html @@ -0,0 +1,42 @@ + + + + + + + Nemo TransferEngine 1.0: List of All Members for TransferDBRecord +
  • Modules
  • +
  • TransferDBRecord
  • +

    List of All Members for TransferDBRecord

    +

    This is the complete list of members for TransferDBRecord, including inherited members.

    + + +
    +
    + + diff --git a/doc/html/transferdbrecord.html b/doc/html/transferdbrecord.html new file mode 100644 index 0000000..de12b41 --- /dev/null +++ b/doc/html/transferdbrecord.html @@ -0,0 +1,88 @@ + + + + + + + Nemo TransferEngine 1.0: TransferDBRecord Class Reference +
  • Modules
  • +
  • TransferDBRecord
  • +
    +

    Contents

    + +
    +

    TransferDBRecord Class Reference

    + +

    The TransferDBRecord class is a simple wrapper class for TransferEngine DBus message. More...

    + +
     #include <TransferDBRecord>
    + +

    Public Types

    + + +
    enum TransferDBRecordField { TransferID, TransferType, Progress, URL, ..., RestartSupported }
    + +

    Public Functions

    + + + + + + +
    TransferDBRecord ()
    TransferDBRecord ( const TransferDBRecord & other )
    ~TransferDBRecord ()
    QVariant value ( int index ) const
    TransferDBRecord & operator= ( const TransferDBRecord & other )
    + +

    Static Public Members

    + + +
    void registerType ()
    + + +
    +

    Detailed Description

    +

    The TransferDBRecord class is a simple wrapper class for TransferEngine DBus message.

    +

    This class wraps transfer method related information and is used to pass that information over the DBus to the any client who is interested in about it.

    +

    A single instance of TransferDBRecord contains information of a one transfer record in TransferEngine database. Usually clients don't need to fill any data to this class, instead they can request a list of TransferDBRecords from the TransferEngine and access its data via value() method.

    +
    + +
    +

    Member Type Documentation

    + +

    enum TransferDBRecord::TransferDBRecordField

    + +
    +
    +

    Member Function Documentation

    + +

    TransferDBRecord::TransferDBRecord ()

    +

    Default constructor.

    + + +

    TransferDBRecord::TransferDBRecord ( const TransferDBRecord & other )

    +

    Copy constructor. Copies the other instance to this.

    + + +

    TransferDBRecord::~TransferDBRecord ()

    +

    Destructor.

    + + +

    void TransferDBRecord::registerType () [static]

    +

    Register TransferDBRecord and QList<TransferDBRecord> as DBus types.

    + + +

    QVariant TransferDBRecord::value ( int index ) const

    +

    Returns any of the TransferDBRecord values based on the index. As an index it's recommended to use TransferDBRecord::TransferDBRecordField enum.

    + + +

    TransferDBRecord & TransferDBRecord::operator= ( const TransferDBRecord & other )

    +

    Assign operator. other is the instance of other TransferDBRecord to copy this instance.

    + +
    + + diff --git a/doc/html/transferengine-members.html b/doc/html/transferengine-members.html new file mode 100644 index 0000000..dec3f17 --- /dev/null +++ b/doc/html/transferengine-members.html @@ -0,0 +1,39 @@ + + + + + + + Nemo TransferEngine 1.0: List of All Members for TransferEngine +
  • Modules
  • +
  • TransferEngine
  • +

    List of All Members for TransferEngine

    +

    This is the complete list of members for TransferEngine, including inherited members.

    + + +
    +
    + + diff --git a/doc/html/transferengine.html b/doc/html/transferengine.html new file mode 100644 index 0000000..7607cbb --- /dev/null +++ b/doc/html/transferengine.html @@ -0,0 +1,195 @@ + + + + + + + Nemo TransferEngine 1.0: TransferEngine Class Reference +
  • Modules
  • +
  • TransferEngine
  • +
    +

    Contents

    + +
    +

    TransferEngine Class Reference

    + +

    The TransferEngine class implements the functionality for different transfer types. More...

    + +
     #include <TransferEngine>
    + +

    Public Functions

    + + + +
    TransferEngine ( QObject * parent = 0 )
    ~TransferEngine ()
    + +

    Public Slots

    + + + + + + + + + + + + + + + +
    void cancelTransfer ( int transferId )
    void clearTransfers ()
    int createDownload ( const QString & displayName, const QString & applicationIcon, const QString & serviceIcon, const QString & filePath, const QString & mimeType, qlonglong expectedFileSize, const QStringList & callback, const QString & cancelMethod, const QString & restartMethod )
    int createSync ( const QString & displayName, const QString & applicationIcon, const QString & serviceIcon, const QStringList & callback, const QString & cancelMethod, const QString & restartMethod )
    void enableNotifications ( bool enable )
    void finishTransfer ( int transferId, int status, const QString & reason )
    bool notificationsEnabled ()
    void restartTransfer ( int transferId )
    void startTransfer ( int transferId )
    QList<TransferMethodInfo> transferMethods ()
    QList<TransferDBRecord> transfers ()
    void updateTransferProgress ( int transferId, double progress )
    int uploadMediaItem ( const QString & source, const QString & serviceId, const QString & mimeType, bool metadataStripped, const QVariantMap & userData )
    int uploadMediaItemContent ( const QVariantMap & content, const QString & serviceId, const QVariantMap & userData )
    + +

    Signals

    + + + + + +
    void progressChanged ( int transferId, double progress )
    void statusChanged ( int transferId, int status )
    void transferMethodListChanged ()
    void transfersChanged ()
    + + +
    +

    Detailed Description

    +

    The TransferEngine class implements the functionality for different transfer types.

    +

    TransferEngine is the central place for:

    + +

    For Downloads and Syncs, the Transfer Engine acts only a place to keep track of these operations. The actual Download and Sync is executed by a client using TransferEngine API. For sharing the TransferEngine provides an API containing a few interaces, which a share plugin must implement. TransferEngine also takes care of loading and executing the sharing, based on the API it defines.

    +

    The most essential thing to remember is that Transfer Engine provides share plugin API, DBus API e.g. for creating Transfer UI or Share UIs, it stores data to the local sqlite database using DbManager and that's it.

    +

    How to implement a share plugin see: TransferPluginInterface, MediaTransferInterface, MediaItem, TransferPluginInfo

    +

    TransferEngine provides DBus API, but instead of using it directly, it's recommended to use TransferEngineClient. If there is a need to create UI to display e.g. transfer statuses, then the DBus API is the recommend way to implement it.

    +
    + +
    +

    Member Function Documentation

    + +

    TransferEngine::TransferEngine ( QObject * parent = 0 )

    +

    Constructor with optional parent arguement.

    + + +

    TransferEngine::~TransferEngine ()

    +

    Destructor.

    + + +

    void TransferEngine::cancelTransfer ( int transferId ) [slot]

    +

    DBus adaptor calls this method to cancel an existing transfer with a transferId.

    +

    If the transfer is Upload, then this method calls MediaTransferInterface instance's cancel method. In a case of Sync or Download this method calls client's cancel callback method, if the one exists.

    +

    Calling this method causes statusChanged() signal to be emitted.

    + + +

    void TransferEngine::clearTransfers () [slot]

    +

    DBus adaptor calls this method to clear all the finished, canceled or interrupted transfers in the database.

    + + +

    int TransferEngine::createDownload ( const QString & displayName, const QString & applicationIcon, const QString & serviceIcon, const QString & filePath, const QString & mimeType, qlonglong expectedFileSize, const QStringList & callback, const QString & cancelMethod, const QString & restartMethod ) [slot]

    +

    DBus adaptor calls this method to create a download entry. Note that this is purely write-only method and doesn't involve anything else from TransferEngine side than creating a new DB record of type 'Download'.

    + +

    This method returns the transfer id of the created Download transfer. Note that this method only creates an entry to the database. To start the actual transfer, the startTransfer() method must be called.

    +

    See also startTransfer(), restartTransfer(), finishTransfer(), and updateTransferProgress().

    + + +

    int TransferEngine::createSync ( const QString & displayName, const QString & applicationIcon, const QString & serviceIcon, const QStringList & callback, const QString & cancelMethod, const QString & restartMethod ) [slot]

    +

    DBus adaptor calls this method to create a Sync entry. Note that this is purely write-only method and doesn't involve anything else from TransferEngine side than creating a new DB record of type 'Download'.

    + +

    This method returns the transfer id of the created Download transfer. Note that this method only creates an entry to the database. To start the actual transfer, the startTransfer() method must be called.

    +

    See also startTransfer(), restartTransfer(), finishTransfer(), and updateTransferProgress().

    + + +

    void TransferEngine::enableNotifications ( bool enable ) [slot]

    +

    DBus adaptor calls this method to enable or disable transfer speicific notifications based on enable argument.

    + + +

    void TransferEngine::finishTransfer ( int transferId, int status, const QString & reason ) [slot]

    +

    Finish an existing Sync or Download transfer with a transferId. Transfer can be finished with different status e.g for successfully finish status can be set to TransferEngineData::TransferFinished, for canceling TransferEngineData::Canceled and for failure with TransferEngineData::TransferInterrupted. In a case of failure, the client can also provide a reason.

    +

    This method causes statusChanged() signal to be emitted. If a sync has been successfully finished, then it will also be removed from the database automatically which causes transferChanged() signal to be emitted.

    + + +

    bool TransferEngine::notificationsEnabled () [slot]

    +

    DBus adaptor calls this method. Returns true or false depending if notifications are enabled or disabled.

    + + +

    void TransferEngine::progressChanged ( int transferId, double progress ) [signal]

    + + +

    void TransferEngine::restartTransfer ( int transferId ) [slot]

    +

    DBus adaptor calls this method to restart a canceled or failed transfer with a \transferId. In a case of Upload, this method creates MediaItem instance of the existing transfer and instantiates the required share plugin. The MediaItem instance is passed to the plugin and sharing is restarted.

    +

    For Sync and Download entries, this method calls their callbacks methods, if a callback interface has been defined by the client originally created the Sync or Download entry.

    + + +

    void TransferEngine::startTransfer ( int transferId ) [slot]

    +

    DBus adaptor calls this method to start the actual transfer. This method changes the transfer status of the existing transfer with a key to TransferEngineData::TransferStarted. This method can only be called for Sync and Download transfers.

    +

    Calling this method causes the corresponding statusChanged() signal to be emitted.

    + + +

    void TransferEngine::statusChanged ( int transferId, int status ) [signal]

    + + +

    void TransferEngine::transferMethodListChanged () [signal]

    + + +

    QList<TransferMethodInfo> TransferEngine::transferMethods () [slot]

    +

    DBus adaptor calls this method to fetch a list of transfer methods. This method returns QList<TransferMethodInfo>.

    +

    Transfer methods are basically a list of share plugins installed to the system.

    + + +

    QList<TransferDBRecord> TransferEngine::transfers () [slot]

    +

    DBus adaptor calls this method to fetch a list of transfers. This method returns QList<TransferDBRecord>.

    + + +

    void TransferEngine::transfersChanged () [signal]

    + + +

    void TransferEngine::updateTransferProgress ( int transferId, double progress ) [slot]

    +

    DBus adaptor calls this method to update transfer progress of the transfer with a transferId and with a new progress.

    + + +

    int TransferEngine::uploadMediaItem ( const QString & source, const QString & serviceId, const QString & mimeType, bool metadataStripped, const QVariantMap & userData ) [slot]

    +

    DBus adaptor calls this method to start uploading a media item. The minimum information needed to start an upload and to create an entry to the transfer database is: source the path to the media item to be downloaded. serviceId the ID of the share plugin. See TransferPluginInterface::pluginId() for more details. mimeType is the MimeType of the media item e.g. "image/jpeg". metadataStripped boolean to indicate if the metadata should be kept or removed before uploading. userData is various kind of data which share UI may provide to the engine. UserData is QVariant map i.e. the data must be provided as key-value pairs, where the keys must be QStrings.

    +

    TransferEngine handles the following user defined data automatically and stores them to the database:

    + +

    In practice this method instantiates a share plugin with serviceId and passes a MediaItem instance filled with required data to it. When the plugin has been loaded, the MediaTransferInterface::start() method is called and the actual sharing starts.

    +

    This method returns a transfer ID which can be used later to fetch information of this specific transfer.

    + + +

    int TransferEngine::uploadMediaItemContent ( const QVariantMap & content, const QString & serviceId, const QVariantMap & userData ) [slot]

    +

    DBus adaptor calls this method to start uploading media item content. Sometimes the content to be shared is not a file, but data e.g. contact information in vcard format. In order to avoid serializing data to a file, pass url to the file, reading the data, deleting the file, TransferEngine provides this convenience API.

    +

    content is the media item content to be shared. serviceId is the id of the share plugin. See TransferPluginInterface::pluginId() for more details. userData is a QVariantMap containing share plugin specific data. See TransferEngine::uploadMediaItem for more details.

    +

    This method returns a transfer ID which can be used later to fetch information of this specific transfer.

    + +
    + + diff --git a/doc/html/transferengine.qch b/doc/html/transferengine.qch new file mode 100644 index 0000000..39e8c8b Binary files /dev/null and b/doc/html/transferengine.qch differ diff --git a/doc/html/transferengine.qhp b/doc/html/transferengine.qhp new file mode 100644 index 0000000..f0e3d55 --- /dev/null +++ b/doc/html/transferengine.qhp @@ -0,0 +1,144 @@ + + + Transfer.Engine.100 + transferengine + + 1.0.0 + transferengine + + + 1.0.0 + transferengine + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + transferengineclient.html + transferdbrecord.html + imageoperation.html + index.html + transferengine.html + transfermethodinfo.html + transferplugininterface.html + callbackinterface.html + dbmanager.html + + + diff --git a/doc/html/transferengineclient-members.html b/doc/html/transferengineclient-members.html new file mode 100644 index 0000000..a98e74e --- /dev/null +++ b/doc/html/transferengineclient-members.html @@ -0,0 +1,23 @@ + + + + + + + Nemo TransferEngine 1.0: List of All Members for TransferEngineClient +
  • Modules
  • +
  • TransferEngineClient
  • +

    List of All Members for TransferEngineClient

    +

    This is the complete list of members for TransferEngineClient, including inherited members.

    + + + diff --git a/doc/html/transferengineclient.html b/doc/html/transferengineclient.html new file mode 100644 index 0000000..fa0b3f8 --- /dev/null +++ b/doc/html/transferengineclient.html @@ -0,0 +1,155 @@ + + + + + + + Nemo TransferEngine 1.0: TransferEngineClient Class Reference +
  • Modules
  • +
  • TransferEngineClient
  • + +

    TransferEngineClient Class Reference

    + +

    The TransferEngineClient class is a simple client API for creating Download and Sync events to TransferEngine. More...

    + +
     #include <TransferEngineClient>
    + +

    Public Types

    + + +
    enum Status { TransferFinished, TransferCanceled, TransferInterrupted }
    + +

    Public Functions

    + + + + + + + + +
    TransferEngineClient ( QObject * parent = 0 )
    ~TransferEngineClient ()
    int createDownloadEvent ( const QString & displayName, const QUrl & applicationIcon, const QUrl & serviceIcon, const QUrl & url, const QString & mimeType, qlonglong expectedFileSize, const CallbackInterface & callback = CallbackInterface() )
    int createSyncEvent ( const QString & displayName, const QUrl & applicationIcon, const QUrl & serviceIcon, const CallbackInterface & callback = CallbackInterface() )
    void finishTransfer ( int transferId, Status status, const QString & reason = QString() )
    void startTransfer ( int transferId )
    void updateTransferProgress ( int transferId, qreal progress )
    + + +
    +

    Detailed Description

    +

    The TransferEngineClient class is a simple client API for creating Download and Sync events to TransferEngine.

    +

    TransferEngineClient is a convenience API for create and updating Download and Sync entries to the Nemo TransferEngine. For Upload entries, it is required to create share plugins by implementing required interfaces provided by this TransferEngine library.

    +

    If the client using this interface wants to enable cancel and restart functionality, it means that the client process must provide DBus API, which Nemo Transfer Engine can call in a case of canceling or restarting the operation. In order to do that client must provide CallbackInterface object with properly set dbus information. See the example below.

    +

    For share plugin implementation:

    +

    To use this API to create e.g. Sync entry see the example below:

    +
     // Create the instance of the client
    + TransferEngineClient *client = new TransferEngineClient(this);
    +
    + // Setup callback information. This is dbus interface
    + CallbackInterface callback("com.jolla.myapp", "/com/jolla/myapp", "com.jolla.myapp",
    +                            "cancel", "restart");
    +
    + // Create the sync event
    + int transferId = client->createSyncEvent("Syncing data from my service",
    +                                        QUrl("image://theme/icon-launcher-my-app"),
    +                                        QUrl("image://theme/icon-s-service-icon"),
    +                                        callback);
    +
    + // Start the actual transfer i.e. sync
    + client->startTransfer(transferId)
    +
    + // Update sync progress. Usually this is done e.g. in a slot which receives sync
    + // progress from a signal.
    + bool ok;
    + qreal progress = 0;
    + while (progress <= 1) {
    + client->updateProgress(transferId, progress);
    + progress = getProgressFoo(&ok);
    +
    + if (!ok)
    +     break;
    + }
    +
    + // End the sync
    + TransferEngineClient status;
    + QString reason;
    + if (ok) {
    +  status = TransferEngineClient::TransferFinished;
    + } else {
    +  status = TnrasferEngineClient::TransferInterrupted;
    +  reason = "Something went wrong";
    + }
    +
    + client->finishTransfer(transferId, status, reason);
    +
    +

    See also TransferPluginInterface, MediaTransferInterface, and TransferPluginInfo.

    + +
    +

    Member Type Documentation

    + +

    enum TransferEngineClient::Status

    +

    This enum type describes different values for the Status.

    + + + + +
    ConstantValueDescription
    TransferEngineClient::TransferFinishedTransferEngineData::TransferFinishedTransfer finished successfully
    TransferEngineClient::TransferCanceledTransferEngineData::TransferCanceledTransfer canceled usually due user actions
    TransferEngineClient::TransferInterruptedTransferEngineData::TransferInterruptedTransfer interrupted because of an error
    + +
    +
    +

    Member Function Documentation

    + +

    TransferEngineClient::TransferEngineClient ( QObject * parent = 0 )

    +

    Construct an instance of TransferEngineClient with optional parent argument.

    + + +

    TransferEngineClient::~TransferEngineClient ()

    +

    Destructor.

    + + +

    int TransferEngineClient::createDownloadEvent ( const QString & displayName, const QUrl & applicationIcon, const QUrl & serviceIcon, const QUrl & url, const QString & mimeType, qlonglong expectedFileSize, const CallbackInterface & callback = CallbackInterface() )

    +

    Creates a download event to the TransferEngine. This method requires the following parameters displayName, a human readable name for the entry. applicationIcon is the QUrl to the icon of the application, who's calling this method. Usually it can be in format "image://theme/icon-s-something". serviceIcon is a service specific icon such as DropBox. url is the url to the media to be downloaded. mimeType is the mimeType of the media.

    +

    Client can define callback functions for canceling and restarting download. For that client can provide optional parameter callback, which is CallbackInterface object containing information about the dbus service.

    +

    Returns transfer id of the download event.

    +

    Create a download event to the TransferEngine. This only creates and entry, and client needs still call:

    +
      +
    • TransferEngineClient::startTransfer(int transferId)
    • +
    • TransferEngineClient::updateTransferProgress(int transferId, qreal progress)
    • +
    • TransferEngineClient::finishTransfer(int transferId, Status status, const QString &reason)
    • +
    +

    See also createSyncEvent(), startTransfer(), updateTransferProgress(), and finishTransfer().

    + + +

    int TransferEngineClient::createSyncEvent ( const QString & displayName, const QUrl & applicationIcon, const QUrl & serviceIcon, const CallbackInterface & callback = CallbackInterface() )

    +

    Create a sync event to the TransferEngine. This method is very similar to

    +

    displayName, a human readable name for the entry. applicationIcon is the QUrl to the icon of the application, who's calling this method. Usually it can be in format "image://theme/icon-s-something". serviceIcon is a service specific icon such as email account.

    +

    Client can define callback functions for canceling and restarting sync. For that client can provide optional parameter callback, which is CallbackInterface object containing information about the dbus service.

    +

    Returns transfer id of the sync event.

    +

    See also createDownload(), except, createSyncEvent(), takes, less, parameters, ., createSyncEvent(), startTransfer(), updateTransferProgress(), and finishTransfer().

    + + +

    void TransferEngineClient::finishTransfer ( int transferId, Status status, const QString & reason = QString() )

    +

    Finalize the transfer with transferId. There are three options for finalizing the transfer by setting the status parameter value:

    + +

    If the client wants to provide reason for finishing the transfer, it's possible to provide reason parameter.

    + + +

    void TransferEngineClient::startTransfer ( int transferId )

    +

    Start the transfer for the existing transfer entry with transferId. This changes the status of the transfer from idle to started.These status changes are handled by Nemo TransferEngine internally, but after this method has been called, the transfer is possible to cancel, interrupt or finish.

    + + +

    void TransferEngineClient::updateTransferProgress ( int transferId, qreal progress )

    +

    Update the progress of the existing transfer with transferId. The progress must be a qreal value between 0 to 1.

    + +
    + + diff --git a/doc/html/transfermethodinfo-members.html b/doc/html/transfermethodinfo-members.html new file mode 100644 index 0000000..3be6006 --- /dev/null +++ b/doc/html/transfermethodinfo-members.html @@ -0,0 +1,28 @@ + + + + + + + Nemo TransferEngine 1.0: List of All Members for TransferMethodInfo +
  • Modules
  • +
  • TransferMethodInfo
  • +

    List of All Members for TransferMethodInfo

    +

    This is the complete list of members for TransferMethodInfo, including inherited members.

    + + + diff --git a/doc/html/transfermethodinfo.html b/doc/html/transfermethodinfo.html new file mode 100644 index 0000000..d4850da --- /dev/null +++ b/doc/html/transfermethodinfo.html @@ -0,0 +1,95 @@ + + + + + + + Nemo TransferEngine 1.0: TransferMethodInfo Class Reference +
  • Modules
  • +
  • TransferMethodInfo
  • + +

    TransferMethodInfo Class Reference

    + +

    The TransferMethodInfo class encapsulate information of a single transfer method. More...

    + +
     #include <TransferMethodInfo>
    + +

    Public Types

    + + +
    enum TransferMethodInfoField { DisplayName, UserName, MethodId, AccountId, ShareUIPath, Capabilities }
    + +

    Public Functions

    + + + + + + +
    TransferMethodInfo ()
    TransferMethodInfo ( const TransferMethodInfo & other )
    ~TransferMethodInfo ()
    QVariant value ( int index ) const
    TransferMethodInfo & operator= ( const TransferMethodInfo & other )
    + +

    Static Public Members

    + + +
    void registerType ()
    + + +
    +

    Detailed Description

    +

    The TransferMethodInfo class encapsulate information of a single transfer method.

    +

    Share plugin must create a list of instances of TransferMethodInfo class to encapsulate information about the plugin for example filling information for the Bluetooth sharing plugin:

    +
     QList<TransferMethodInfo> infoList;
    + TransferMethodInfo info;
    +
    + QStringList capabilities;
    + capabilities << QLatin1String("*");
    +
    + info.displayName     = QLatin1String("Bluetooth");
    + info.userName        = "";
    + info.accountId       = "";
    + info.methodId        = QLatin1String("bluetooth");
    + info.shareUIPath     = SHARE_UI_PATH + QLatin1String("/BluetoothShareUI.qml");
    + info.capabilitities  = capabilities;
    + infoList << info;
    +
    + +
    +

    Member Type Documentation

    + +

    enum TransferMethodInfo::TransferMethodInfoField

    + +
    +
    +

    Member Function Documentation

    + +

    TransferMethodInfo::TransferMethodInfo ()

    + + +

    TransferMethodInfo::TransferMethodInfo ( const TransferMethodInfo & other )

    + + +

    TransferMethodInfo::~TransferMethodInfo ()

    + + +

    void TransferMethodInfo::registerType () [static]

    + + +

    QVariant TransferMethodInfo::value ( int index ) const

    +

    Returns the value using the index. Actually the index is enum TransferMethodInfoField.

    + + +

    TransferMethodInfo & TransferMethodInfo::operator= ( const TransferMethodInfo & other )

    + +
    + + diff --git a/doc/html/transferplugininterface-members.html b/doc/html/transferplugininterface-members.html new file mode 100644 index 0000000..03c1ad6 --- /dev/null +++ b/doc/html/transferplugininterface-members.html @@ -0,0 +1,19 @@ + + + + + + + Nemo TransferEngine 1.0: List of All Members for TransferPluginInterface +
  • Modules
  • +
  • TransferPluginInterface
  • +

    List of All Members for TransferPluginInterface

    +

    This is the complete list of members for TransferPluginInterface, including inherited members.

    + + + diff --git a/doc/html/transferplugininterface.html b/doc/html/transferplugininterface.html new file mode 100644 index 0000000..4804651 --- /dev/null +++ b/doc/html/transferplugininterface.html @@ -0,0 +1,66 @@ + + + + + + + Nemo TransferEngine 1.0: TransferPluginInterface Class Reference +
  • Modules
  • +
  • TransferPluginInterface
  • + +

    TransferPluginInterface Class Reference

    + +

    The TransferPluginInterface class defines an abstract interface for each TransferEngine share plugins to implement. More...

    + +
     #include <TransferPluginInterface>
    + +

    Public Functions

    + + + + + +
    virtual bool enabled () const = 0
    virtual TransferPluginInfo * infoObject () = 0
    virtual QString pluginId () const = 0
    virtual MediaTransferInterface * transferObject () = 0
    + + +
    +

    Detailed Description

    +

    The TransferPluginInterface class defines an abstract interface for each TransferEngine share plugins to implement.

    +

    TransferEngine supports C++ share plugins. Each share plugin must implement couple of well defined interfaces:

    +
      +
    • TransferPluginInterface Provides interfaces to access required objects to start sharing.
    • +
    • MediaTransferInterface Implements the actual sharing functionality
    • +
    • TransferPluginInfo Provides information about plugin status such as is it ready.
    • +
    +

    TransferPluginInterface provides information to the TransferEngine via this interface.

    +
    + +
    +

    Member Function Documentation

    + +

    bool TransferPluginInterface::enabled () const [pure virtual]

    +

    Return true or false depending if the plugin is enabled or not

    + + +

    TransferPluginInfo * TransferPluginInterface::infoObject () [pure virtual]

    +

    Return TransferPluginInfo object

    + + +

    QString TransferPluginInterface::pluginId () const [pure virtual]

    +

    Return a plugin id e.g. Facebook, Twitter, etc.

    + + +

    MediaTransferInterface * TransferPluginInterface::transferObject () [pure virtual]

    +

    Return MediaTransferInterface object

    + +
    + + diff --git a/doc/src/index.qdoc b/doc/src/index.qdoc new file mode 100644 index 0000000..7268443 --- /dev/null +++ b/doc/src/index.qdoc @@ -0,0 +1,90 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the Jolla Ltd nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR +** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************************/ + +/*! +\contentspage {Nemo Transfer Engine Contents} +\page index.html + +\title Nemo Transfer Engine + +The Nemo Transfer Engine is a daemon process which takes care of tracking sharing, sync and downloads. +In addition to just tracking those operations, it provides an API to create new share plugins and different +functionality related these operations.The Nemo Transfer Engine doesn't provide any UI components, but the +plugin interface expects sharing UIs to be written as QML. + +The Nemo Transfer Engine can be understood as a front end to the database which contain all the information +about sharing, syncs and downloads. For syncs and downloads it acts only as storage manager so clients can +use Nemo Transfer Engine client API to create and update sync and download events. For sharing, Nemo Transfer +Engine provides own API and supports share plugins. + +See TransferEngine DbManager + + +\section2 Nemo Transfer Engine API + +The API can be divided in two different parts: the share plugin API and the client API. + +\section3 Share Plugin API + +Share plugin is a Qt plugin, which must be implemented using C++ interfaces defined by Nemo Transfer Engine. +The plugins must be installed to the specific location where Nemo Transfer Engine loads them. The actual +share functionality implementation depends on the client e.g. if it's HW specific like NFC or online service +such as Facebook. Each plugin must implement or use the following interface: + +\list + \o \l {TransferPluginInterface} Share plugin must implement this interface + \o \l {MediaTransferInterface} Share plugin must implement this interface + \o \l {TransferPluginInfo} Share plugin must provide information about plugin using this class + \o \l {TransferMethodInfo} Share plugin must provide information about e.g. accounts using this class +\endlist + +\section3 Client API + +Client API can also be divided in two sections: full features DBus API and TransferEngineClient Interface. +The first one supports all the features Nemo Transfer Engine provides and makes possible to implement for +example Transfer UI and client side sharing interface on top of it. The TransferEngineClient is meant to +be used by clients who want to inform Nemo Transfer Engine of ongoing Sync or Downloads. + +\list + \o DBus API - see org.nemomobile.transferengine.xml. For the client side it will generate TransferEngineInterface + class which can be used directly. + \o TransferEngineClient - The convenience API to create Sync and Download events. +\endlist + +\section3 Reference +\list + \o \l {Nemo Transfer Engine Reference} +\endlist + +*/ diff --git a/doc/src/mediaplugininterface.qdoc b/doc/src/mediaplugininterface.qdoc new file mode 100644 index 0000000..f6c5422 --- /dev/null +++ b/doc/src/mediaplugininterface.qdoc @@ -0,0 +1,76 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the Jolla Ltd nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR +** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************************/ + +/*! + \class TransferPluginInterface + \brief The TransferPluginInterface class defines an abstract interface for each TransferEngine share plugins to implement. + + \ingroup transfer-engine-lib + + TransferEngine supports C++ share plugins. Each share plugin must implement couple of well defined interfaces: + + \list + \o \l TransferPluginInterface Provides interfaces to access required objects to start sharing. + \o \l MediaTransferInterface Implements the actual sharing functionality + \o \l TransferPluginInfo Provides information about plugin status such as is it ready. + \endlist + + TransferPluginInterface provides information to the TransferEngine via this interface. +*/ + +/*! + \fn MediaTransferInterface * TransferPluginInterface::transferObject() = 0 + + Return MediaTransferInterface object + */ + +/*! + \fn virtual TransferPluginInfo *TransferPluginInterface::infoObject() = 0 + + Return TransferPluginInfo object + */ + +/*! + \fn virtual QString TransferPluginInterface::pluginId() const = 0 + + Return a plugin id e.g. Facebook, Twitter, etc. + */ + +/*! + \fn virtual bool TransferPluginInterface::enabled() const = 0 + + Return true or false depending if the plugin is enabled or not + */ + + diff --git a/doc/src/transfer-engine-all.qdoc b/doc/src/transfer-engine-all.qdoc new file mode 100644 index 0000000..dda9f8b --- /dev/null +++ b/doc/src/transfer-engine-all.qdoc @@ -0,0 +1,54 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the Jolla Ltd nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR +** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************************/ + +/*! + +\page transfer-engine-all.html +\title Nemo Transfer Engine Reference + +\section1 Nemo Transfer Engine + +Classes used in the engine side. + +\annotatedlist transfer-engine + + +\section1 Transfer Engine Lib + +Library components + +\annotatedlist transfer-engine-lib + +*/ + diff --git a/doc/src/transferplugininfo.qdoc b/doc/src/transferplugininfo.qdoc new file mode 100644 index 0000000..9fbe164 --- /dev/null +++ b/doc/src/transferplugininfo.qdoc @@ -0,0 +1,82 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the Jolla Ltd nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR +** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************************/ + +/*! + \class TransferPluginInfo + \brief The TransferPluginInfo class is an abstract class encapsulates information about share plugin. + + \ingroup transfer-engine-lib + + TransferPluginInfo provides information about single share plugin via TransferMethodInfo + class. Because one plugin can support multiple accounts e.g. user can have one, two or + more Facebook accounts, this class provides a list of TransferMethodInfo object instances. +*/ + +/*! + \fn virtual QList TransferPluginInfo::info() const = 0 + + Subclass must implement this method and provide at least one TransferMethodInfo + object instance. If a plugin supports multiple accounts e.g. more than one Facebook + account, then list must contain one TransferMethodEntry per enabled account. + + Returns a list of TransferMethodInfo objects. +*/ + +/*! + \fn virtual void TransferPluginInfo::query() = 0 + + Subclass must implement this method and make sure that when info is available + infoReady() signal will be emitted. If TransferMethodInfo data is ready, calling this + method should just emit infoReady() signal. +*/ + +/*! + \fn virtual bool TransferPluginInfo::ready() const = 0 + + Deprecated. implment this, but it won't be used. +*/ + +/*! + \fn void TransferPluginInfo::infoReady() + + Subclass must emit this signal when info() method is ready to return + a list of TransferMethodInfo data. +*/ + +/*! + \fn void TransferPluginInfo::infoError(const QString &msg) + + Subclass must emit this signal with an error \a msg if there's an error i.e. info() method + can't return a list of TransferMethodInfo objects. +*/ diff --git a/doc/transfer-engine-project.qdocconf b/doc/transfer-engine-project.qdocconf new file mode 100644 index 0000000..8c5da07 --- /dev/null +++ b/doc/transfer-engine-project.qdocconf @@ -0,0 +1,64 @@ +include(config/compat.qdocconf) +include(config/macros.qdocconf) +include(config/qt-cpp-ignore.qdocconf) +include(config/qt-defines.qdocconf) + +indexes = src/qt.index + +language = Cpp + +sourceencoding = UTF-8 +outputencoding = UTF-8 +naturallanguage = en_US + +project = Nemo TransferEngine +description = Nemo TransferEngine Library Reference Documentation +versionsym = +version = 1.0 +url = + +sources.fileextensions = "*.cpp *.qdoc *.mm *.qml" +headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx" +examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml" +examples.imageextensions = "*.png *.jpeg *.jpg *.gif *.mng" + +# don't include ../../components/*.qml in sourcedirs, that causes qdoc3 to parse the +# .qml files, not find any docs, and conclude they are internal + +sourcedirs = ../../src ../../lib +headerdirs = ../../src ../../lib + +#excludedirs = + +#exampledirs = ../../examples + +#imagedirs = images \ +# ../src/images + +#outputformats = HTML +outputdir = html +tagfile = html/transfer-engine.tags +base = file:../html + +#outputprefixes = QML +#outputprefixes.QML = qml-transfer-engine- + +qhp.projects = TransferEngine + +qhp.TransferEngine.file = transferengine.qhp +qhp.TransferEngine.namespace = Transfer.Engine.100 +qhp.TransferEngine.virtualFolder = transferengine +qhp.TransferEngine.indexTitle = Nemo Transfer Engine Reference Documentation +qhp.TransferEngine.indexRoot = + +qhp.TransferEngine.filterAttributes = transferengine 1.0.0 +qhp.TransferEngine.customFilters.TransferEngine.name = Nemo TransferEngine 1.0.0 +qhp.TransferEngine.customFilters.TransferEngine.filterAttributes = transferengine 1.0.0 +#qhp.TransferEngine.subprojects.examples.title = Examples +#qhp.TransferEngine.subprojects.examples.indexTitle = Nemo Transfer Engine Examples +#qhp.TransferEngine.subprojects.examples.selectors = fake:example +#qhp.TransferEngine.subprojects.examples.sortPages = true +#qhp.TransferEngine.subprojects.tutorials.title = Tutorials +#qhp.TransferEngine.subprojects.tutorials.indexTitle = Nemo TransferEngine Tutorials +#qhp.TransferEngine.subprojects.tutorials.selectors = fake:tutorial +#qhp.TransferEngine.subprojects.tutorials.sortPages = true diff --git a/lib/imageoperation.cpp b/lib/imageoperation.cpp new file mode 100644 index 0000000..d018f4b --- /dev/null +++ b/lib/imageoperation.cpp @@ -0,0 +1,202 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include "imageoperation.h" +#include + +#include +#include +#include +#include + +/*! + \class ImageOperation + \brief The ImageOperation class is a helper class to manipulate images. + + This class is meant to be used by share plugins. It can be used for: + \list + \o Removing image metadata + \o Scaling image + \o Create a temp files from the image paths + \endlist +*/ + +/*! + Creates a file path from the \a sourceFilePath to the \a path location. + If the path is not given it uses system default temp path e.g. '/var/tmp'. + This function uses sourceFilePath as a template to generate a temp file name. + + NOTE: This function doesn't create the file, it only generates the file path to + the temporary file. + + Temporary file will be e.g: + + Source file: "/home/nemo/Pictures/img_001.jpg" + Temporary file: "/var/tmp/img_001_0.jpg" + */ +QString ImageOperation::uniqueFilePath(const QString &sourceFilePath, const QString &path) +{ + if (sourceFilePath.isEmpty() || !QFile::exists(sourceFilePath)) { + qWarning() << Q_FUNC_INFO << sourceFilePath << "Doesn't exist or then the path is empty!"; + return QString(); + } + + if (path.isEmpty()) { + qWarning() << Q_FUNC_INFO << "'path' argument is empty!"; + return QString(); + } + + QFileInfo fileInfo(sourceFilePath); + + + // Construct target temp file path first: + QDir dir(path); + QStringList prevFiles = dir.entryList(QStringList() << fileInfo.baseName() + QLatin1String("*"), QDir::Files); + int count = prevFiles.count(); + + // Create temp file with increasing index in a file name e.g. + // /var/temp/img_001_0.jpg, /var/temp/img_001_1.jpg + // In a case there already is a file with the same filename + QString filePath = dir.absolutePath() + QDir::separator(); + QString fileName = fileInfo.baseName() + + QLatin1String("_") + + QString::number(count) + + QLatin1String(".") + + fileInfo.suffix(); + + // This makes sure that we don't generate a file name which already exists. E.g. there are files: + // img_001_0, img_001_1, img_001_2 and img_001 gets deleted. Then this code would generate a + // filename img_001_2 which already exists + while(prevFiles.contains(fileName)) { + ++count; + fileName = fileInfo.baseName() + + QLatin1String("_") + + QString::number(count) + + QLatin1String(".") + + fileInfo.suffix(); + } + + return filePath + fileName; +} + +/*! + Helper method to remove metadata from jpeg files. Only author and location related + metadata will be removed. \a sourceFile is the path to the original file. + + Returns a path to the copy of the image with metadata removed. + */ +QString ImageOperation::removeImageMetadata(const QString &sourceFile) +{ + + if (!QuillMetadata::canRead(sourceFile)) { + qWarning() << Q_FUNC_INFO << "Can't read the source: " << sourceFile; + return QString(); + } + + QString targetFile = uniqueFilePath(sourceFile); + + // Copy image content first + if (!QFile::copy(sourceFile, targetFile)) { + qWarning() << Q_FUNC_INFO << "Failed to copy content!"; + return QString(); + } + + // Get metadata and remove it + QuillMetadata md(sourceFile); + if(!md.isValid()) { + qWarning() << Q_FUNC_INFO << "Invalid metadata"; + return QString(); + } + + // Remove bunch of metadata entries + md.removeEntry(QuillMetadata::Tag_Creator); + md.removeEntry(QuillMetadata::Tag_Subject); + md.removeEntry(QuillMetadata::Tag_Title); + md.removeEntry(QuillMetadata::Tag_City); + md.removeEntry(QuillMetadata::Tag_Country); + md.removeEntry(QuillMetadata::Tag_Location); + md.removeEntry(QuillMetadata::Tag_Description); + md.removeEntry(QuillMetadata::Tag_Regions); + md.removeEntry(QuillMetadata::Tag_Timestamp); + md.removeEntries(QuillMetadata::TagGroup_GPS); + + // Write modified metadata to the target file + if (!md.write(targetFile)) { + qWarning() << Q_FUNC_INFO << "Failed to clear metadata!"; + return QString(); + } + // Return new file with removed metadata + return targetFile; +} + +/*! + Scale image \a sourceFile using \a scaleFactor. The scaled image is stored to the \a targetFile or + if \a targetFile is not given, then a temporary file is created for saving. + + The \a scaleFactor argument must be greater than 0 and less than 1. This function returns path to the + scaled image. Note that if user doesn't specify \a targetFile the scaled image is stored under temp + directory. Nothing guarantees that created file will remain in that diretory forewer so the caller is + reponsible of copying file for more permanent storing. + + Returns a path to the scaled image. + + It is also recommended that if the caller doesn't use the scaled file, which is stored to the temp + directory later, the caller should remove the file. + */ +QString ImageOperation::scaleImage(const QString &sourceFile, qreal scaleFactor, const QString &targetFile) +{ + if ( scaleFactor <= 0.0 || 1.0 <= scaleFactor) { + qWarning() << Q_FUNC_INFO << "Argument scaleFactor needs to be 0 < scale factor < 1"; + return QString(); + } + + if (!QFile::exists(sourceFile)) { + qWarning() << Q_FUNC_INFO << sourceFile << "doesn't exist!"; + return QString(); + } + + QString tmpFile = targetFile; + if (tmpFile.isEmpty()) { + tmpFile = uniqueFilePath(sourceFile); + } + + // Using just basic QImage scale here. We can easily replace this implementation later, if we notice + // performance bottlenecks here. + QImage tmpImg(sourceFile); + if (tmpImg.isNull()) { + qWarning() << Q_FUNC_INFO << "Null source image!"; + return QString(); + } + + QImage scaled = tmpImg.scaled(tmpImg.size() * scaleFactor, Qt::KeepAspectRatio, Qt::SmoothTransformation); + + if (!scaled.save(tmpFile)) { + qWarning() << Q_FUNC_INFO << "Failed to save scaled image to temp file!"; + return QString(); + } + + return tmpFile; +} diff --git a/lib/imageoperation.h b/lib/imageoperation.h new file mode 100644 index 0000000..b8b34b5 --- /dev/null +++ b/lib/imageoperation.h @@ -0,0 +1,41 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef IMAGEOPERATION_H +#define IMAGEOPERATION_H + +#include +#include + +class ImageOperation +{ +public: + static QString uniqueFilePath(const QString &sourceFilePath, const QString &path = QDir::tempPath()); + static QString removeImageMetadata(const QString &sourceFile); + static QString scaleImage(const QString &sourceFile, qreal scaleFactor, const QString &targetFile=QString()); +}; + +#endif // IMAGEOPERATION_H diff --git a/lib/lib.pro b/lib/lib.pro new file mode 100644 index 0000000..fbec10d --- /dev/null +++ b/lib/lib.pro @@ -0,0 +1,53 @@ +TEMPLATE = lib +TARGET = nemotransferengine +DEPENDPATH += . +INCLUDEPATH += . +CONFIG += shared link_pkgconfig +QT += dbus +CONFIG += quillmetadata + +system(qdbusxml2cpp -v -c TransferEngineInterface -p transferengineinterface.h:transferengineinterface.cpp -i metatypedeclarations.h ../dbus/org.nemo.transferengine.xml) + +HEADERS += \ + transferdbrecord.h \ + metatypedeclarations.h \ + transfertypes.h \ + mediatransferinterface.h \ + transferplugininterface.h \ + mediaitem.h \ + transfermethodinfo.h \ + transferplugininfo.h \ + transferengineclient.h \ + imageoperation.h + +SOURCES += \ + transferdbrecord.cpp \ + mediatransferinterface.cpp \ + mediaitem.cpp \ + transfermethodinfo.cpp \ + transferengineclient.cpp \ + imageoperation.cpp + +# generated files +HEADERS += \ + transferengineinterface.h + + +SOURCES += \ + transferengineinterface.cpp + +OTHER_FILES += nemotransfernegine.pc nemotransferengine-plugin.prf + +headers.files = $$HEADERS +headers.path = /usr/include/TransferEngine + +target.path = /usr/lib + +pkgconfigpc.path = /usr/lib/pkgconfig/ +pkgconfigpc.files = nemotransferengine.pc + +prf.path = $$[QT_INSTALL_DATA]/mkspecs/features +prf.files = nemotransferengine-plugin.prf + + +INSTALLS += target headers prf pkgconfigpc diff --git a/lib/mediaitem.cpp b/lib/mediaitem.cpp new file mode 100644 index 0000000..ae4df71 --- /dev/null +++ b/lib/mediaitem.cpp @@ -0,0 +1,127 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include "mediaitem.h" +#include + +class MediaItemPrivate +{ +public: + MediaItemPrivate() + {} + + QMap m_values; +}; + +/*! + \class MediaItem + \brief The MediaItem class is a container for all the media item related data needed for sharing. + + \ingroup transfer-engine-lib + + MediaItem is used internally by Nemo Transfer Engine, but MediaItem object instance is + passed to each share plugin via MediaTransferInterface and it is meant to be a read-only object. + + MediaItem can be accessed via MediaTransferInterface::mediaItem() method. MediaItem stores internal + data as key-value pairs. Data can be accessed via value() method using pre-defined ValueKey keys. + + Note: Depending on the use case (sharing, download, sync) MediaItem may not contain data for all + the keys. For example when MediaItem is created for the sync event, it doesn't contain Url or + MimeType values or if plugin doesn't require account, then AccountId won't be defined for this + MediaItem. + + Depending on the share UI which plugins provides, the content of the MediaItem varies. Bluetooth or + NFC sharing doesn't need account or descriptio, but then again Facebook sharing needs that information. + + \sa value() MediaTransferInterface::MediaItem() + */ + +/*! + \enum MediaItem::ValueKey + + The following enum values can be used for accessing MediaItem data. Modifying MediaItem data is not + allowed for the plugins. + + \value TransferType Type of the transfer + \value Timestamp Time stamp when event has been created + \value Status Transfer status + \value DisplayName Name of the share plugin or for sync and download event + \value Url URL of the media item to be shared or downloaded + \value MimeType Mimetype of the media item to be shared or downloaded + \value FileSize Filesize of the media item + \value PluginId Id of the share plugin + \value MetadataStripped Flag to indicate if metadata should be stripped or not + \value Title Title for the media item to be transfered + \value Description Description for the media item to be transfered + \value ServiceIcon Service icon URL e.g. email service + \value ApplicationIcon Application icon url + \value AccountId, Account Id + \value UserData User specific data that is passed from the UI + \value Callback Callback service, path, interface packed to QStringList + \value CancelCBMethod Cancel callback method name + \value RestartCBMethod Restart callback method name + \value CancelSupported Bool to indicate if cancel is supported by the share plugin + \value RestartSupported Bool to indicate if restart is supported by the share plugin +*/ + +/*! + Create MediaItem object. + */ +MediaItem::MediaItem(QObject *parent): + QObject(parent), + d_ptr(new MediaItemPrivate) +{ +} + +/*! + Destructor. + */ +MediaItem::~MediaItem() +{ + delete d_ptr; + d_ptr = 0; +} + +/*! + Set \a value for the \a key. + */ +void MediaItem::setValue(ValueKey key, const QVariant &value) +{ + Q_D(MediaItem); + d->m_values.insert(key, value); +} + +/*! + Returns the value of the \a key. +*/ +QVariant MediaItem::value(ValueKey key) const +{ + Q_D(const MediaItem); + if (!d->m_values.contains(key)) { + return QVariant(); + } + return d->m_values.value(key); +} diff --git a/lib/mediaitem.h b/lib/mediaitem.h new file mode 100644 index 0000000..32a8649 --- /dev/null +++ b/lib/mediaitem.h @@ -0,0 +1,89 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef MEDIAITEM_H +#define MEDIAITEM_H +#include +#include + +// Originally this was meant to be exposed to QML side, but not anymore. +class MediaItemPrivate; +class MediaItem: public QObject +{ + +public: + + enum ValueKey { + TransferType, + Timestamp, + Status, + DisplayName, + Url, + ContentData, + ResourceName, + MimeType, + FileSize, + PluginId, + MetadataStripped, + ScalePercent, + Title, + Description, + ServiceIcon, + ApplicationIcon, + ThumbnailIcon, + AccountId, + UserData, + + // Callback methods comes from the API, not from the plugins + Callback, + CancelCBMethod, + RestartCBMethod, + + // These come from plugins. + CancelSupported, + RestartSupported + + }; + + explicit MediaItem(QObject *parent = 0); + ~MediaItem(); + + QVariant value(ValueKey key) const; + +protected: + void setValue(ValueKey key, const QVariant &value); + + +private: + MediaItemPrivate *d_ptr; + Q_DECLARE_PRIVATE(MediaItem) + friend class TransferEngine; + friend class TransferEnginePrivate; + friend class DbManager; + friend class ut_mediatransferinterface; +}; + +#endif // MEDIAITEM_H diff --git a/lib/mediatransferinterface.cpp b/lib/mediatransferinterface.cpp new file mode 100644 index 0000000..cc0d97b --- /dev/null +++ b/lib/mediatransferinterface.cpp @@ -0,0 +1,291 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include "mediatransferinterface.h" +#include "mediaitem.h" +#include + +// Update progress (to dbus) only in every 5% progress changes +#define PROGRESS_THRESHOLD 0.05 + +class MediaTransferInterfacePrivate +{ +public: + MediaTransferInterfacePrivate(): + m_mediaItem(0), + m_status(MediaTransferInterface::NotStarted), + m_progress(0), + m_prevProgress(0) + {} + + MediaItem *m_mediaItem; + MediaTransferInterface::TransferStatus m_status; + qreal m_progress; + qreal m_prevProgress; +}; + + + + +/*! + \class MediaTransferInterface + \brief The MediaTransferInterface class is responsible of implementing + + \ingroup transfer-engine-lib + + MediaTransferInterface is an abstract class which must be implemented by + each share plugin. The subclass of this class is resposible of providing: + + \list + \o Status information of the sharing + \o Progress of the sharing + \o Information, if cancel and restart actions are supported + \o Starting and/or canceling the sharing + \endlist + + + The flow: + The instance of this class is created when SailfishShare::start() method is + called. +*/ + +/*! + \enum MediaTransferInterface::TransferStatus + + Transfers status + + \value NotStarted Transfer not started + \value TransferStarted Transfer is ongoing + \value TransferCanceled Transfer is canceled usually via user actions + \value TransferFinished Transfer is finished successfully + \value TransferInterrupted Transfer failed +*/ + +/*! + \fn virtual QString MediaTransferInterface::displayName() const = 0 + + Subclass must implement this method. Return a human readable display + name for the service e.g. "Facebook". + */ + +/*! + \fn virtual QUrl MediaTransferInterface::serviceIcon() const = 0 + + Subclass must implement this method. Return the URL to the service + icon. Service icon can be e.g. Facebook or BT icon. + + */ + + +/*! + \fn virtual bool MediaTransferInterface::cancelEnabled() const = 0 + + Subclass must implement this method. Return true if cancel is supported + or false otherwise. + */ + +/*! + \fn virtual bool MediaTransferInterface::restartEnabled() const = 0 + + Subclass must implement this method. Return true if restart is supported + or false otherwise. + */ + +/*! + \fn virtual void MediaTransferInterface::start() = 0 + + Subclass must implement this to start the actual sharing operation. This + same method is called when sharing is restarted. + */ + +/*! + \fn virtual void MediaTransferInterface::cancel() = 0 + + Subclass must implement this to cancel the ongoing share operation. +*/ + + +/*! + \fn void MediaTransferInterface::statusChanged(MediaTransferInterface::TransferStatus status) + + This signal with changed \a status is emitted when setStatus() is called. + + Note that this signal is NOT meant to be emitted by the subclass. Instead of + emitting it manually the subclass should use setStatus() method, which causes + this signal to be emitted automatically. +*/ + +/*! + \fn void MediaTransferInterface::progressUpdated(qreal progress) + + This signal is emitted when the \a progress changes. Progress is changed when the + subclass calls setProgress() method. + + Note that, like the statusChanged() signal, also this signal is not to meant to be + emitted by the subclass. It's emitted automatically when subclass calls setProgress(). +*/ + + + +/*! + Construct MediaTransferInterface object with optional \a parent object. + */ +MediaTransferInterface::MediaTransferInterface(QObject *parent): + QObject(parent), + d_ptr(new MediaTransferInterfacePrivate) +{} + +/*! + Destructor. + */ +MediaTransferInterface::~MediaTransferInterface() +{ + delete d_ptr; + d_ptr = 0; +} + +/*! + Set MediaItem for this object. MediaItem is a container for all the information related + to the \a mediaItem (image, video, vcard,..) which is going to be shared. This information + must contain e.g. url to the media item. For more details all the available values, + see MediaItem::ValueKey. + + NOTE: That the values set to this media item depends on the related Share UI. For example + BT share UI won't provide information related to the accounts because "accountId" or "description" + are not required for the Bluetooh. But then again Facebook share UI provides this information. + This means that because plugin provides the Share UI, it knows which fields are set for the + MediaItem instance. + + MediaItem is passed to this item by TransferEngine. + + */ +void MediaTransferInterface::setMediaItem(MediaItem *mediaItem) +{ + Q_D(MediaTransferInterface); + if (d->m_mediaItem) { + qWarning() << "MediaTransferInterface::setMediaItem: MediaItem is not null. Old media item will be deleted!"; + delete d->m_mediaItem; + } + d->m_mediaItem = mediaItem; + d->m_mediaItem->setParent(this); +} + +/*! + Return the MediaItem instance or 0, if it hasn't been set. + */ +MediaItem *MediaTransferInterface::mediaItem() +{ + Q_D(MediaTransferInterface); + return d->m_mediaItem; +} + + +/*! + Returns the status of the media transfer. +*/ +MediaTransferInterface::TransferStatus MediaTransferInterface::status() const +{ + Q_D(const MediaTransferInterface); + return d->m_status; +} + +/*! + Returns the current progress of the ongoing media transfer. +*/ +qreal MediaTransferInterface::progress() const +{ + Q_D(const MediaTransferInterface); + return d->m_progress; +} + + +/*! + Sets the \a status for the media transfer. Note that this method also + sets the progress if status changes to MediaTransferInterface::TransferFinished. + If status changes to MediaTransferInterface::TransferCanceled or + MediaTransferInterface::TransferInterrupted, the progress is set to 0. + + This method emits statusChanged() and progressUpdated() signals automatically based + on status changes and if this method marks progress to 1 or to 0. +*/ +void MediaTransferInterface::setStatus(TransferStatus status) +{ + Q_D(MediaTransferInterface); + + // Make sure that progress is 1 if we are really finished + if (status == MediaTransferInterface::TransferFinished && + d->m_prevProgress < 1 ) { + d->m_progress = 1; + d->m_prevProgress = 1; + emit progressUpdated(1); + } + + // Make sure that progress is set to 0 if transfer is canceled or + // interrupted + if (status == MediaTransferInterface::TransferCanceled || + status == MediaTransferInterface::TransferInterrupted) { + d->m_progress = 0; + d->m_prevProgress = 0; + emit progressUpdated(0); + } + + // And update the status + if (d->m_status != status) { + d->m_status = status; + emit statusChanged(d->m_status); + } + +} + +/*! + Set the \a progress for the on going media transfer. + + Note that progressUpdated() signal might not be emitted in every call of this method + because it might pollute dbus if progress changes too many times. + */ +void MediaTransferInterface::setProgress(qreal progress) +{ + Q_D(MediaTransferInterface); + if (progress < 0 || 1 < progress) { + qWarning() << "MediaTransferInterface::setProgress: progress must be in between 0 and 1"; + // Just show the warning and let the progress update. Sometimes there might be some + // decimals which may not match exactly with 1, like 1.0001 + } + + if (d->m_progress == progress) { + return; + } + + d->m_progress = progress; + + // To avoid dbus overload let's not emit this signal in every progress change + if (qAbs(d->m_progress - d->m_prevProgress) >= PROGRESS_THRESHOLD) { + emit progressUpdated(progress); + d->m_prevProgress = progress; + } +} + + diff --git a/lib/mediatransferinterface.h b/lib/mediatransferinterface.h new file mode 100644 index 0000000..a61fe81 --- /dev/null +++ b/lib/mediatransferinterface.h @@ -0,0 +1,86 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef MEDIATRANSFERINTERFACE_H +#define MEDIATRANSFERINTERFACE_H +#include +#include +#include "transfertypes.h" + + +class MediaItem; +class MediaTransferInterfacePrivate; + +class MediaTransferInterface: public QObject +{ + Q_OBJECT +public: + + enum TransferStatus { + NotStarted = TransferEngineData::NotStarted, + TransferStarted = TransferEngineData::TransferStarted, + TransferCanceled = TransferEngineData::TransferCanceled, + TransferFinished = TransferEngineData::TransferFinished, + TransferInterrupted = TransferEngineData::TransferInterrupted + }; + + + explicit MediaTransferInterface(QObject *parent = 0); + virtual ~MediaTransferInterface(); + + MediaItem *mediaItem(); + + + virtual QString displayName() const = 0; + virtual QUrl serviceIcon() const = 0; + virtual bool cancelEnabled() const = 0; + virtual bool restartEnabled() const = 0; + + MediaTransferInterface::TransferStatus status() const; + qreal progress() const; + +protected: + void setMediaItem(MediaItem *mediaItem); + void setStatus(MediaTransferInterface::TransferStatus status); + void setProgress(qreal progress); + +public Q_SLOTS: + virtual void start() = 0; + virtual void cancel() = 0; + +Q_SIGNALS: + void statusChanged(MediaTransferInterface::TransferStatus status); + void progressUpdated(qreal progress); + +private: + MediaTransferInterfacePrivate *d_ptr; + Q_DECLARE_PRIVATE(MediaTransferInterface) + friend class TransferEngine; + friend class TransferEnginePrivate; + friend class DbManager; +}; + +#endif // MEDIATRANSFERINTERFACE_H diff --git a/lib/metatypedeclarations.h b/lib/metatypedeclarations.h new file mode 100644 index 0000000..5abb866 --- /dev/null +++ b/lib/metatypedeclarations.h @@ -0,0 +1,40 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef METATYPEDECLARATIONS_H +#define METATYPEDECLARATIONS_H + +#include "transferdbrecord.h" +#include "transfermethodinfo.h" +#include + +Q_DECLARE_METATYPE(TransferDBRecord) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(TransferMethodInfo) +Q_DECLARE_METATYPE(QList) + + +#endif // METATYPEDECLARATIONS_H diff --git a/lib/nemotransferengine-plugin.prf b/lib/nemotransferengine-plugin.prf new file mode 100644 index 0000000..f545014 --- /dev/null +++ b/lib/nemotransferengine-plugin.prf @@ -0,0 +1,26 @@ +################################################################### +# transferengine plugin feature +################################################################### + +!contains(DEFINES, BUILD_LIBTRANSFERENGINE) { + + CONFIG += qt plugin + QT += network + + LIBTRANSFERENGINE_INC_DIR = /usr/include/TransferEngine + + INCLUDEPATH += $${LIBTRANSFERENGINE_INC_DIR} + DEPENDPATH += $${LIBTRANSFERENGINE_INC_DIR} + + # We need to include these for MOC. + HEADERS += $${INCLUDEPATH}/transferplugininterface.h + HEADERS += $${INCLUDEPATH}/mediatransferinterface.h + + LIBTRANSFERENGINE_LIB_DIR = /usr/lib + unix: QMAKE_FLAGS += $${QMAKE_LFLAGS_RPATH}$${LIBTRANSFERENGINE_LIB_DIR} + LIBS += -L$${LIBTRANSFERENGINE_LIB_DIR} + qtAddLibrary(nemotransferengine) +} + + + diff --git a/lib/nemotransferengine.pc b/lib/nemotransferengine.pc new file mode 100644 index 0000000..3ee0d53 --- /dev/null +++ b/lib/nemotransferengine.pc @@ -0,0 +1,11 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/TransferEngine + +Name: libnemotransferengine +Description: Nemo transfer engine library for share plugins and transfer engine API +Version: 0.0.1 +Requires: QtCore QtDBus +Libs: -L${libdir} -lnemotransferengine +Cflags: -I${includedir} diff --git a/lib/transferdbrecord.cpp b/lib/transferdbrecord.cpp new file mode 100644 index 0000000..367ccfa --- /dev/null +++ b/lib/transferdbrecord.cpp @@ -0,0 +1,253 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include "transferdbrecord.h" +#include "metatypedeclarations.h" + +#include + +/*! + \class TransferDBRecord + \brief The TransferDBRecord class is a wrapper class for TransferEngine DBus message. + + \ingroup transfer-engine-lib + + This class wraps transfer method related information and is used to pass that information + over the DBus to the any client who is interested in about it. + + A single instance of TransferDBRecord contains information of a one transfer record in TransferEngine + database. Usually clients don't need to fill any data to this class, instead they can request a list + of TransferDBRecords from the TransferEngine and access its data via value() method. + */ + +/*! + \enum TransferDBRecord::TransferDBRecordField + + An enum for accessing TrasnferDBRecord values using value() method + + \value TransferID Id of the transfer + \value TransferType Type of the transfer (Upload, Download, Sync + \value Progress Progress of the transfer + \value URL Url of the media related to the transfer + \value Status The status of the transfer + \value PluginID The id of the plugin which is handling the transfer + \value Timestamp The timestamp for the transfer + \value DisplayName The display name for the transfer + \value ResourceName The name of the resource + \value MimeType MimeType information of the media being transfered + \value FileSize File size of the media being transfered + \value ServiceIcon Icon url for a service related to the transfer + \value ApplicationIcon Application icon url which has created e.g. sync or download transfer + \value ThumbnailIcon Thumbnail url + \value CancelSupported Boolean to indicate if cancel is supported + \value RestartSupported Boolean to indicate if cancel is supported +*/ + +/*! + Default constructor. + */ +TransferDBRecord::TransferDBRecord() +{ + +} + + +/*! + Assigns \a other to this transfer db record and returns a reference to this transfer db record. + */ +TransferDBRecord &TransferDBRecord::operator=(const TransferDBRecord &other) +{ + transfer_id = other.transfer_id; + transfer_type = other.transfer_type; + status = other.status; + size = other.size; + progress = other.progress; + plugin_id = other.plugin_id; + url = other.url; + timestamp = other.timestamp; + display_name = other.display_name; + resource_name = other.resource_name; + mime_type = other.mime_type; + service_icon = other.service_icon; + application_icon= other.application_icon; + thumbnail_icon = other.thumbnail_icon; + cancel_supported = other.cancel_supported; + restart_supported = other.restart_supported; + return *this; +} + +/*! + Constructs a copy of \a other. + */ +TransferDBRecord::TransferDBRecord(const TransferDBRecord &other): + transfer_id(other.transfer_id), + transfer_type(other.transfer_type), + status(other.status), + size(other.size), + progress(other.progress), + plugin_id(other.plugin_id), + url(other.url), + timestamp(other.timestamp), + display_name(other.display_name), + resource_name(other.resource_name), + mime_type(other.mime_type), + service_icon(other.service_icon), + application_icon(other.application_icon), + thumbnail_icon(other.thumbnail_icon), + cancel_supported(other.cancel_supported), + restart_supported(other.restart_supported) +{ +} + +/*! + Destroys the transfer db record. + */ +TransferDBRecord::~TransferDBRecord() +{ +} + +/*! + Writes the given \a record to specified \a argument. +*/ +QDBusArgument &operator<<(QDBusArgument &argument, const TransferDBRecord &record) +{ + argument.beginStructure(); + + argument << record.transfer_id + << record.transfer_type + << record.status + << record.size + << record.progress + << record.plugin_id + << record.url + << record.timestamp + << record.display_name + << record.resource_name + << record.mime_type + << record.service_icon + << record.application_icon + << record.thumbnail_icon + << record.cancel_supported + << record.restart_supported; + argument.endStructure(); + return argument; +} + + +/*! + Reads the given \a argument and stores it to the specified \a record. +*/ +const QDBusArgument &operator>>(const QDBusArgument &argument, TransferDBRecord &record) +{ + argument.beginStructure(); + argument >> record.transfer_id + >> record.transfer_type + >> record.status + >> record.size + >> record.progress + >> record.plugin_id + >> record.url + >> record.timestamp + >> record.display_name + >> record.resource_name + >> record.mime_type + >> record.service_icon + >> record.application_icon + >> record.thumbnail_icon + >> record.cancel_supported + >> record.restart_supported; + argument.endStructure(); + return argument; +} + +/*! + Registers TransferDBRecord and QList as DBus types. + */ +void TransferDBRecord::registerType() +{ + qDBusRegisterMetaType(); + qDBusRegisterMetaType >(); +} + +/*! + Returns any of the TransferDBRecord values based on the index. As an \a index it's recommended to use + TransferDBRecord::TransferDBRecordField enum. +*/ +QVariant TransferDBRecord::value(int index) const +{ + switch(index) { + case TransferID: + return transfer_id; + + case TransferType: + return transfer_type; + + case Progress: + return progress; + + case URL: + return url; + + case Status: + return status; + + case PluginID: + return plugin_id; + + case Timestamp: + return timestamp; + + case DisplayName: + return display_name; + + case ResourceName: + return resource_name; + + case MimeType: + return mime_type; + + case FileSize: + return size; + + case ServiceIcon: + return service_icon; + + case ApplicationIcon: + return application_icon; + + case ThumbnailIcon: + return thumbnail_icon; + + case CancelSupported: + return cancel_supported; + + case RestartSupported: + return restart_supported; + + default: + return QVariant(); + } +} diff --git a/lib/transferdbrecord.h b/lib/transferdbrecord.h new file mode 100644 index 0000000..71fd05e --- /dev/null +++ b/lib/transferdbrecord.h @@ -0,0 +1,92 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef TRANSFERDBRECORD_H +#define TRANSFERDBRECORD_H + +#include +#include + +class TransferDBRecord +{ + +public: + + enum TransferDBRecordField { + TransferID = 0, + TransferType, + Progress, + URL, + Status, + PluginID, + Timestamp, + DisplayName, + ResourceName, + MimeType, + FileSize, + ServiceIcon, + ApplicationIcon, + ThumbnailIcon, + CancelSupported, + RestartSupported + }; + + TransferDBRecord(); + TransferDBRecord &operator=(const TransferDBRecord &other); + TransferDBRecord(const TransferDBRecord &other); + ~TransferDBRecord(); + + + friend QDBusArgument &operator<<(QDBusArgument &argument, const TransferDBRecord &record); + friend const QDBusArgument &operator>>(const QDBusArgument &argument, TransferDBRecord &record); + + static void registerType(); + + QVariant value(int index) const; + +// TODO: Maybe this could use QVariantList internally to ease of pain of keeping thigs up to date +// when database structure / fields change + int transfer_id; + int transfer_type; + int status; + qint64 size; + double progress; + QString plugin_id; + QString url; + QString timestamp; + QString display_name; + QString resource_name; + QString mime_type; + QString service_icon; + QString application_icon; + QString thumbnail_icon; + bool cancel_supported; + bool restart_supported; +}; + + + +#endif // DBUSTYPES_H diff --git a/lib/transferengineclient.cpp b/lib/transferengineclient.cpp new file mode 100644 index 0000000..a6cfbfc --- /dev/null +++ b/lib/transferengineclient.cpp @@ -0,0 +1,341 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include "transferengineclient.h" +#include "transferengineinterface.h" + + +class CallbackInterfacePrivate { +public: + CallbackInterfacePrivate() + { + } + + CallbackInterfacePrivate(const QString &server, const QString &path, const QString &interface, + const QString &cancelMethod, const QString &restartMethod) + { + callback << server << path << interface; + m_cancelMethod = cancelMethod; + m_restartMethod = restartMethod; + } + + QStringList callback; + QString m_cancelMethod; + QString m_restartMethod; +}; + + +/*! + \class CallbackInterface + \brief The CallbackInterface class is a convenience class to wrap DBus callback infromation for + TransferEngineClient API. + + \ingroup transfer-engine-lib + + This class should be used with TransferEngineClient API. + + NOTE: If creating an instance of this class to the heap, the caller is responsible of freeing + the allocated memory. + + \sa TransferEngineClient::createSyncEvent() TransferEngineClient::createDownloadEvent() + */ + + +/*! + Construct an empty CallbackInterface. This can be used if client doesn't want to provide callback + interface to the Sync or Download events. + */ +CallbackInterface::CallbackInterface() + : d_ptr(new CallbackInterfacePrivate()) +{ +} + + +/*! + Construct CallbackInterface instance to provide callback information to the TransferEngineClient. Setup + arguments as: + \list + \o \a server e.g. "com.jolla.myapp" + \o \a path e.g. "/com/jolla/myapp" + \o \a interface e.g. "com.jolla.myapp" + \o \a cancelMethod Cancel method name e.g. "cancelSync" + \o \a restartMethod Restart method name e.g. "restartSync" + \endlist + */ +CallbackInterface::CallbackInterface(const QString &server, const QString &path, const QString &interface, + const QString &cancelMethod, const QString &restartMethod) + : d_ptr(new CallbackInterfacePrivate(server, path, interface, cancelMethod, restartMethod)) +{ +} + +/*! + Destroys CallbackInterface object. + */ +CallbackInterface::~CallbackInterface() +{ + delete d_ptr; +} + + +class TransferEngineClientPrivate +{ +public: + TransferEngineInterface *m_client; +}; + +/*! + \class TransferEngineClient + \brief The TransferEngineClient class is a simple client API for creating Download and + Sync events to TransferEngine. + + TransferEngineClient is a convenience API for create and updating Download and + Sync entries to the Nemo TransferEngine. For Upload entries, it is required to + create share plugins by implementing required interfaces provided by this TransferEngine + library. + + If the client using this interface wants to enable cancel and restart functionality, it + means that the client process must provide DBus API, which Nemo Transfer Engine can call + in a case of canceling or restarting the operation. In order to do that client must provide + CallbackInterface object with properly set dbus information. See the example below. + + For share plugin implementation: + \sa TransferPluginInterface, MediaTransferInterface, TransferPluginInfo + + To use this API to create e.g. Sync entry see the example below: + + \code + + // Create the instance of the client + TransferEngineClient *client = new TransferEngineClient(this); + + // Setup callback information. This is dbus interface + CallbackInterface callback("com.jolla.myapp", "/com/jolla/myapp", "com.jolla.myapp", + "cancel", "restart"); + + // Create the sync event + int transferId = client->createSyncEvent("Syncing data from my service", + QUrl("image://theme/icon-launcher-my-app"), + QUrl("image://theme/icon-s-service-icon"), + callback); + + // Start the actual transfer i.e. sync + client->startTransfer(transferId) + + // Update sync progress. Usually this is done e.g. in a slot which receives sync + // progress from a signal. + bool ok; + qreal progress = 0; + while (progress <= 1) { + client->updateProgress(transferId, progress); + progress = getProgressFoo(&ok); + + if (!ok) + break; + } + + // End the sync + TransferEngineClient status; + QString reason; + if (ok) { + status = TransferEngineClient::TransferFinished; + } else { + status = TnrasferEngineClient::TransferInterrupted; + reason = "Something went wrong"; + } + + client->finishTransfer(transferId, status, reason); + + \endcode +*/ +/*! + \enum TransferEngineClient::Status + + This enum type describes different values for the Status. + + \value TransferFinished Transfer finished successfully + \value TransferCanceled Transfer canceled usually due user actions + \value TransferInterrupted Transfer interrupted because of an error +*/ + +/*! + Construct an instance of TransferEngineClient with optional \a parent argument. + */ +TransferEngineClient::TransferEngineClient(QObject *parent) : + QObject(parent), + d_ptr(new TransferEngineClientPrivate) +{ + Q_D(TransferEngineClient); + d->m_client = new TransferEngineInterface("org.nemo.transferengine", + "/org/nemo/transferengine", + QDBusConnection::sessionBus(), + this); +} + + +/*! + Destructor. + */ +TransferEngineClient::~TransferEngineClient() +{ + Q_D(TransferEngineClient); + delete d->m_client; + delete d_ptr; + d_ptr = 0; +} + +/*! + Creates a download event to the TransferEngine. This method requires the following parameters + \a displayName, a human readable name for the entry. \a applicationIcon is the \c QUrl to the icon + of the application, who's calling this method. Usually it can be in format "image://theme/icon-s-something". + \a serviceIcon is a service specific icon such as DropBox. \a url is the url to the media to be downloaded. + \a mimeType is the mimeType of the media and \a expectedFileSize is the file size of the file to be downloaded. + + Client can define callback functions for canceling and restarting download. For that client can provide + optional parameter \a callback, which is \c CallbackInterface object containing information about the dbus + service. + + Returns transfer id of the download event. + + Create a download event to the TransferEngine. This only creates and entry, and client + needs still call: + \list + \o \l TransferEngineClient::startTransfer() + \o \l TransferEngineClient::updateTransferProgress() + \o \l TransferEngineClient::finishTransfer() + \endlist + + \sa createSyncEvent(), startTransfer(), updateTransferProgress(), finishTransfer() + */ +int TransferEngineClient::createDownloadEvent(const QString &displayName, + const QUrl &applicationIcon, + const QUrl &serviceIcon, + const QUrl &url, + const QString &mimeType, + qlonglong expectedFileSize, + const CallbackInterface &callback) +{ + Q_D(const TransferEngineClient); + QDBusPendingReply reply = d->m_client->createDownload(displayName, + applicationIcon.toString(), + serviceIcon.toString(), + url.toString(), + mimeType, + expectedFileSize, + callback.d_func()->callback, + callback.d_func()->m_cancelMethod, + callback.d_func()->m_restartMethod); + reply.waitForFinished(); + + if (reply.isError()) { + qWarning() << "TransferEngineClient::createDownloadEvent: failed to get transfer ID!"; + return false; + } + + return reply.value(); +} + +/*! + Create a sync event to the TransferEngine. This method is very similar to createDownload(), + except createSyncEvent() takes less parameters. + + \a displayName, a human readable name for the entry. \a applicationIcon is the \c QUrl to the icon + of the application, who's calling this method. Usually it can be in format "image://theme/icon-s-something". + \a serviceIcon is a service specific icon such as email account. + + Client can define callback functions for canceling and restarting sync. For that client can provide + optional parameter \a callback, which is \c CallbackInterface object containing information about the dbus + service. + + Returns transfer id of the sync event. + + \sa startTransfer(), updateTransferProgress(), finishTransfer() + */ +int TransferEngineClient::createSyncEvent(const QString &displayName, + const QUrl &applicationIcon, + const QUrl &serviceIcon, + const CallbackInterface &callback) +{ + Q_D(const TransferEngineClient); + QDBusPendingReply reply = d->m_client->createSync(displayName, + applicationIcon.toString(), + serviceIcon.toString(), + callback.d_func()->callback, + callback.d_func()->m_cancelMethod, + callback.d_func()->m_restartMethod); + reply.waitForFinished(); + + if (reply.isError()) { + qWarning() << "TransferEngineClient::createSyncEvent: failed to get transfer ID!"; + return false; + } + + return reply.value(); +} + +/*! + Start the transfer for the existing transfer entry with \a transferId. This changes the status of the + transfer from idle to started.These status changes are handled by Nemo TransferEngine internally, but + after this method has been called, the transfer is possible to cancel, interrupt or finish. + */ +void TransferEngineClient::startTransfer(int transferId) +{ + Q_D(const TransferEngineClient); + d->m_client->startTransfer(transferId); +} + +/*! + Update the progress of the existing transfer with \a transferId. The \a progress must be a \c qreal value + between 0 to 1. + + */ +void TransferEngineClient::updateTransferProgress(int transferId, qreal progress) +{ + if (progress < 0 || 1 < progress) { + qWarning() << Q_FUNC_INFO << "Progress must be between 0 and 1!"; + return; + } + Q_D(const TransferEngineClient); + d->m_client->updateTransferProgress(transferId, progress); +} + +/*! + Finalize the transfer with \a transferId. There are three options for finalizing the transfer by setting + the \a status parameter value: + \list + \o \l TransferEngineClient::TransferFinished - success + \o \l TransferEngineClient::TransferCanceled - user cancelation + \o \l TransferEngineClient::TransferInterrupted - an error + \endlist + + If the client wants to provide reason for finishing the transfer, it's possible to provide \a reason + parameter. + */ +void TransferEngineClient::finishTransfer(int transferId, Status status, const QString &reason) +{ + Q_D(const TransferEngineClient); + d->m_client->finishTransfer(transferId, static_cast(status), reason); +} + diff --git a/lib/transferengineclient.h b/lib/transferengineclient.h new file mode 100644 index 0000000..031773a --- /dev/null +++ b/lib/transferengineclient.h @@ -0,0 +1,89 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef TRANSFERENGINECLIENT_H +#define TRANSFERENGINECLIENT_H + +#include +#include +#include "transfertypes.h" + + +class CallbackInterfacePrivate; +class CallbackInterface { +public: + CallbackInterface(); + CallbackInterface(const QString &server, const QString &path, const QString &interface, + const QString &cancelMethod, const QString &restartMethod); + ~CallbackInterface(); + +private: + CallbackInterfacePrivate *d_ptr; + Q_DECLARE_PRIVATE(CallbackInterface) + friend class TransferEngineClient; +}; + +class TransferEngineClientPrivate; +class TransferEngineClient : public QObject +{ + Q_OBJECT +public: + + enum Status { + TransferFinished = TransferEngineData::TransferFinished, + TransferCanceled = TransferEngineData::TransferCanceled, + TransferInterrupted = TransferEngineData::TransferInterrupted + }; + + explicit TransferEngineClient(QObject *parent = 0); + ~TransferEngineClient(); + + + + int createDownloadEvent(const QString &displayName, + const QUrl &applicationIcon, + const QUrl &serviceIcon, + const QUrl &url, + const QString &mimeType, + qlonglong expectedFileSize, + const CallbackInterface &callback = CallbackInterface()); + + + int createSyncEvent(const QString &displayName, + const QUrl &applicationIcon, + const QUrl &serviceIcon, + const CallbackInterface &callback = CallbackInterface()); + + void startTransfer(int transferId); + void updateTransferProgress(int transferId, qreal progress); + void finishTransfer(int transferId, Status status, const QString &reason = QString()); + +private: + TransferEngineClientPrivate *d_ptr; + Q_DECLARE_PRIVATE(TransferEngineClient) +}; + +#endif // TRANSFERENGINECLIENT_H diff --git a/lib/transfermethodinfo.cpp b/lib/transfermethodinfo.cpp new file mode 100644 index 0000000..564159c --- /dev/null +++ b/lib/transfermethodinfo.cpp @@ -0,0 +1,182 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include "transfermethodinfo.h" +#include "metatypedeclarations.h" + +/*! + \class TransferMethodInfo + \brief The TransferMethodInfo class encapsulate information of a single transfer method. + + \ingroup transfer-engine-lib + + Share plugin must create a list of instances of TransferMethodInfo class to encapsulate + information about the plugin for example filling information for the Bluetooth sharing plugin: + + \code + QList infoList; + TransferMethodInfo info; + + QStringList capabilities; + capabilities << QLatin1String("*"); + + info.displayName = QLatin1String("Bluetooth"); + info.userName = ""; + info.accountId = ""; + info.methodId = QLatin1String("bluetooth"); + info.shareUIPath = SHARE_UI_PATH + QLatin1String("/BluetoothShareUI.qml"); + info.capabilitities = capabilities; + infoList << info; + \endcode +*/ + +/*! + \enum TransferMethodInfo::TransferMethodInfoField + + This enum can be used for accessing different values using value() method + + \value DisplayName The name that will be visible e.g. Facebook or Bluetooth + \value UserName User name e.g. mike.myers@gmail.com + \value MethodId The plugin Id of the share plugin e.g. "bluetooth" + \value AccountId The Id the account, needed in a case of multiple accounts + \value ShareUIPath The path to the share ui QML plugin. This QML file will be loaded by the share UI + \value Capabilities A list of supported mimetypes +*/ + +/*! + Creates an instance of TransferMethodInfo. + */ +TransferMethodInfo::TransferMethodInfo(): + displayName(), + userName(), + methodId(), + shareUIPath(), + capabilitities(), + accountId() +{ +} + +/*! + Assigns \a other object to this. +*/ +TransferMethodInfo &TransferMethodInfo::operator=(const TransferMethodInfo &other) +{ + displayName = other.displayName; + userName = other.userName; + methodId = other.methodId; + shareUIPath = other.shareUIPath; + capabilitities = other.capabilitities; + accountId = other.accountId; + return *this; +} + +/*! + Copies \a other to this instance. +*/ +TransferMethodInfo::TransferMethodInfo(const TransferMethodInfo &other): + displayName(other.displayName), + userName(other.userName), + methodId(other.methodId), + shareUIPath(other.shareUIPath), + capabilitities(other.capabilitities), + accountId(other.accountId) +{ + +} + +/*! + Destroys TransferMethodInfo instance. +*/ +TransferMethodInfo::~TransferMethodInfo() +{ + +} + +/*! + Writes data from \a info to \a argument. +*/ +QDBusArgument &operator<<(QDBusArgument &argument, const TransferMethodInfo &info) +{ + argument.beginStructure(); + argument << info.displayName + << info.userName + << info.methodId + << info.shareUIPath + << info.capabilitities + << info.accountId; + + argument.endStructure(); + return argument; +} + +/*! + Reads data from \a argument to \a info. +*/ +const QDBusArgument &operator>>(const QDBusArgument &argument, TransferMethodInfo &info) +{ + argument.beginStructure(); + argument >> info.displayName + >> info.userName + >> info.methodId + >> info.shareUIPath + >> info.capabilitities + >> info.accountId; + + argument.endStructure(); + return argument; +} + +/*! + Registers TransferMethodInfo and QList as DBus types. +*/ +void TransferMethodInfo::registerType() +{ + qDBusRegisterMetaType(); + qDBusRegisterMetaType >(); +} + +/*! + Returns the value using the \a index. Actually the index is enum TransferMethodInfoField. + */ +QVariant TransferMethodInfo::value(int index) const +{ + switch(index) { + case DisplayName: + return displayName; + case UserName: + return userName; + case MethodId: + return methodId; + case ShareUIPath: + return shareUIPath; + case Capabilities: + return capabilitities; + case AccountId: + return accountId; + default: + return QVariant(); + } +} diff --git a/lib/transfermethodinfo.h b/lib/transfermethodinfo.h new file mode 100644 index 0000000..dbc96ee --- /dev/null +++ b/lib/transfermethodinfo.h @@ -0,0 +1,69 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef TRANSFERMETHODINFO_H +#define TRANSFERMETHODINFO_H + +#include +#include + + +class TransferMethodInfo +{ +public: + + // Used internally only + enum TransferMethodInfoField { + DisplayName, // e.g. Facebook + UserName, // e.g. mike.myers@gmail.com + MethodId, // Id of the plugin + AccountId, // Id the account, needed in a case of multiple accounts + ShareUIPath, // path to the share ui QML plugin + Capabilities // list of supported mimetypes + }; + + TransferMethodInfo(); + TransferMethodInfo &operator=(const TransferMethodInfo &other); + TransferMethodInfo(const TransferMethodInfo &other); + ~TransferMethodInfo(); + + friend QDBusArgument &operator<<(QDBusArgument &argument, const TransferMethodInfo &record); + friend const QDBusArgument &operator>>(const QDBusArgument &argument, TransferMethodInfo &record); + + static void registerType(); + + QVariant value(int index) const; + + + QString displayName; + QString userName; + QString methodId; + QString shareUIPath; + QStringList capabilitities; + quint32 accountId; +}; + +#endif // TRANSFERMETHODINFO_H diff --git a/lib/transferplugininfo.h b/lib/transferplugininfo.h new file mode 100644 index 0000000..0e649cd --- /dev/null +++ b/lib/transferplugininfo.h @@ -0,0 +1,45 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef TRANSFERPLUGININFO_H +#define TRANSFERPLUGININFO_H +#include +#include "transfermethodinfo.h" + +class TransferPluginInfo: public QObject +{ + Q_OBJECT +public: + virtual QList info() const = 0; + virtual void query() = 0; + virtual bool ready() const = 0; + +Q_SIGNALS: + void infoReady(); + void infoError(const QString &msg); +}; + +#endif // TRANSFERPLUGINSTATUS_H diff --git a/lib/transferplugininterface.h b/lib/transferplugininterface.h new file mode 100644 index 0000000..c9d869b --- /dev/null +++ b/lib/transferplugininterface.h @@ -0,0 +1,48 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef TRANSFERPLUGININTERFACE_H +#define TRANSFERPLUGININTERFACE_H + +#include +#include "transferplugininfo.h" + + +class MediaTransferInterface; +class TransferPluginInterface +{ +public: + virtual MediaTransferInterface * transferObject() = 0; + + virtual TransferPluginInfo *infoObject() = 0; + + virtual QString pluginId() const = 0; + + virtual bool enabled() const = 0; +}; + +Q_DECLARE_INTERFACE(TransferPluginInterface, "org.nemo.TransferPluginInterface/1.0") +#endif // TRANSFERPLUGININTERFACE_H diff --git a/lib/transfertypes.h b/lib/transfertypes.h new file mode 100644 index 0000000..cc89b5e --- /dev/null +++ b/lib/transfertypes.h @@ -0,0 +1,50 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef TRANSFERTYPES_H +#define TRANSFERTYPES_H + +namespace TransferEngineData +{ + + enum TransferStatus { + Unknown, + NotStarted, + TransferStarted, + TransferCanceled, + TransferFinished, + TransferInterrupted + }; + + enum TransferType { + Undefined, + Upload, + Download, + Sync + }; + +} +#endif // TRANSFERTYPES_H diff --git a/license.lgpl b/license.lgpl new file mode 100644 index 0000000..0c063d3 --- /dev/null +++ b/license.lgpl @@ -0,0 +1,514 @@ + GNU LESSER GENERAL PUBLIC LICENSE + + Nemo Transfer Engine + Copyright (C) 2013 Jolla Ltd. + Contact: info@jolla.com + + You may use, distribute and copy the Nemo Transfer Engine + under the terms of GNU Lesser General Public License version 2.1. + +------------------------------------------------------------------------- + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation + and appearing in the file license.lgpl included in the packaging + of this file. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/nemo-transfer-engine.conf b/nemo-transfer-engine.conf new file mode 100644 index 0000000..a68d894 --- /dev/null +++ b/nemo-transfer-engine.conf @@ -0,0 +1,5 @@ +[transfers] +service=com.jolla.settings +path=/com/jolla/settings/ui +interface=com.jolla.settings.ui +method=showTransfers diff --git a/rpm/transfer-engine.spec b/rpm/transfer-engine.spec new file mode 100644 index 0000000..66a9e14 --- /dev/null +++ b/rpm/transfer-engine.spec @@ -0,0 +1,120 @@ +Name: nemo-transferengine +Version: 0.0.14 +Release: 0 +Summary: Transfer Engine for uploading media content and tracking transfers. +Group: System Environment/Daemon +License: LGPLv2.1 +URL: https://github.com/nemomobile/transfer-engine +Source0: %{name}-%{version}.tar.gz +BuildRequires: pkgconfig(QtCore) +BuildRequires: pkgconfig(accounts-qt) +BuildRequires: pkgconfig(qmsystem2) +BuildRequires: pkgconfig(QtSystemInfo) +BuildRequires: desktop-file-utils +BuildRequires: pkgconfig(mlite) +BuildRequires: pkgconfig(accounts-qt) +BuildRequires: pkgconfig(quillmetadata) + +%description +%{summary}. + +%files +%defattr(-,root,root,-) +%{_libdir}/*.so* +%{_bindir}/nemo-transfer-engine +%{_datadir}/dbus-1/services/org.nemo.transferengine.service +%{_datadir}/translations/nemo-transfer-engine_eng_en.qm +/home/nemo/.config/nemomobile/*.conf + + +%package -n nemo-transferengine-devel +Summary: Development headers for transfer engine library. +Group: Development/Libraries +Requires: nemo-transferengine = %{version} + +%description -n nemo-transferengine-devel +%{summary}. + +%files -n nemo-transferengine-devel +%defattr(-,root,root,-) +%{_includedir}/TransferEngine/*.h +%{_qt_datadir}/mkspecs/features/nemotransferengine-plugin.prf +%{_libdir}/pkgconfig/nemotransferengine.pc + +%package ts-devel +Summary: Translation source for Nemo TransferEngine +License: LGPLv2.1 +Group: System Environment/Daemon + +%description ts-devel +Translation source for Nemo TransferEngine + +%files ts-devel +%defattr(-,root,root,-) +%{_datadir}/translations/source/nemo-transfer-engine.ts + +%package tests +Summary: Unit tests for Nemo TransferEngine +License: LGPLv2.1 +Group: System Environment/Daemon + +%description tests +Unit tests for Nemo TransferEngine + +%files tests +%defattr(-,root,root,-) +/opt/tests/nemo-transfer-engine/* + +%package doc +Summary: Documentation for Nemo TransferEngine +License: BSD +Group: System Environment/Daemon + +%description doc +Documentation for Nemo TransferEngine + +%files doc +%defattr(-,root,root,-) +/usr/share/doc/nemo-transfer-engine/* + + + +%prep +%setup -q -n %{name}-%{version} + +%build + +%qmake + +make %{?jobs:-j%jobs} +make docs + +%install +rm -rf %{buildroot} +%qmake_install + +%define def_uid $(grep "^UID_MIN" /etc/login.defs | tr -s " " | cut -d " " -f2) +%define def_user $(getent passwd %def_uid | sed 's/:.*//') +%define db_file /home/%{def_user}/.local/nemo-transferengine/transferdb.sqlite +%define te_pid $(pgrep -f nemo-transfer-engine) + +%post -n nemo-transferengine +/sbin/ldconfig +if [ -n "%{te_pid}" ] +then + kill -s 10 %{te_pid} +fi + +chown nemo:nemo -R /home/%{def_user}/.config/nemomobile +chmod u+rw -R /home/%{def_user}/.config/nemomobile + +exit 0 + +%postun -n nemo-transferengine +/sbin/ldconfig + +if [ -f "%{db_file}" ] +then + rm %{db_file} +fi +exit 0 diff --git a/src/dbmanager.cpp b/src/dbmanager.cpp new file mode 100644 index 0000000..cd4abde --- /dev/null +++ b/src/dbmanager.cpp @@ -0,0 +1,778 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include "dbmanager.h" +#include "transfertypes.h" +#include "mediaitem.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DB_PATH ".local/nemo-transferengine" +#define DB_NAME "transferdb.sqlite" + +// Table for metadata +#define DROP_METADATA "DROP TABLE metadata;" +#define TABLE_METADATA "CREATE TABLE metadata (metadata_id INTEGER PRIMARY KEY AUTOINCREMENT,\n" \ + "title TEXT,\n" \ + "description TEXT,\n" \ + "transfer_id INTEGER NOT NULL,\n" \ + "FOREIGN KEY(transfer_id) REFERENCES transfers(transfer_id) ON DELETE CASCADE\n" \ + ");\n" + +// Table for callbacks. In practice there are dbus interfaces +#define DROP_CALLBACK "DROP TABLE callback;" +#define TABLE_CALLBACK "CREATE TABLE callback (callback_id INTEGER PRIMARY KEY AUTOINCREMENT,\n" \ + "service TEXT,\n" \ + "path TEXT,\n" \ + "interface TEXT,\n"\ + "cancel_method TEXT,\n"\ + "restart_method TEXT,\n"\ + "transfer_id INTEGER NOT NULL,\n"\ + "FOREIGN KEY(transfer_id) REFERENCES transfers(transfer_id) ON DELETE CASCADE\n"\ + ");\n" + +// Table for all the transfers +#define DROP_TRANSFERS "DROP TABLE transfers;" +#define TABLE_TRANSFERS "CREATE TABLE transfers (transfer_id INTEGER PRIMARY KEY AUTOINCREMENT,\n" \ + "transfer_type INTEGER,\n" \ + "timestamp TEXT,\n" \ + "status INTEGER,\n" \ + "progress REAL,\n" \ + "display_name TEXT,\n" \ + "application_icon TEXT,\n"\ + "thumbnail_icon TEXT,\n"\ + "service_icon TEXT,\n" \ + "url TEXT,\n" \ + "resource_name TEXT,\n" \ + "mime_type TEXT,\n" \ + "file_size INTEGER,\n" \ + "plugin_id TEXT,\n" \ + "account_id TEXT,\n"\ + "strip_metadata INTEGER,\n" \ + "scale_percent REAL,\n" \ + "cancel_supported INTEGER,\n" \ + "restart_supported INTEGER\n" \ + ");\n" + +// Cascade trigger i.e. when transfer is removed and it has metadata or callbacks, this +// trigger make sure that they are also removed +#define DROP_TRIGGER "DROP TRIGGER delete_cascade;" +#define TRIGGER "CREATE TRIGGER delete_cascade\n" \ + "BEFORE DELETE ON transfers\n" \ + "FOR EACH ROW BEGIN\n" \ + " DELETE FROM metadata WHERE transfer_id = OLD.transfer_id;\n" \ + " DELETE FROM callback WHERE transfer_id = OLD.transfer_id;\n" \ + "END;\n" + +// Update the following version if database schema changes. +#define USER_VERSION 1 +#define PRAGMA_USER_VERSION QString("PRAGMA user_version=%1").arg(USER_VERSION) + +class DbManagerPrivate { +public: + + QString currentDateTime() + { + // TODO: Make sure this can handle time correctly + // Let's use ISO8601 strings + QDateTime dt = QDateTime::currentDateTime(); + return dt.toString("yyyy-MM-ddThh:mm:ss"); + } + + bool createDatabaseSchema() + { + bool ok = true; + QSqlQuery query; + if (!query.exec(TABLE_METADATA)) { + qWarning() << "DbManagerPrivate::createDatabase: create metadata table: " + << query.lastError().text() << ":" << query.lastError().databaseText(); + ok = false; + } + if (!query.exec(TABLE_CALLBACK)) { + qWarning() << "DbManagerPrivate::createDatabase: create callback table: " + << query.lastError().text() << ":" << query.lastError().databaseText(); + ok = false; + } + if (!query.exec(TABLE_TRANSFERS)) { + qWarning() << "DbManagerPrivate::createDatabase: create transfer table: " + << query.lastError().text() << ":" << query.lastError().databaseText(); + ok = false; + } + if (!query.exec(TRIGGER)) { + qWarning() << "DbManagerPrivate::createDatabase: create cascade trigger: " + << query.lastError().text() << ":" << query.lastError().databaseText(); + ok = false; + } + if (!query.exec(PRAGMA_USER_VERSION)) { + qWarning() << "DbManagerPrivate::createDatabase: pragma user_version: " + << query.lastError().text() << ":" << query.lastError().databaseText(); + ok = false; + } + query.finish(); + return ok; + } + + bool deleteOldTables() + { + bool ok = true; + QSqlQuery query; + if (!query.exec(DROP_TRIGGER)) { + qWarning() << Q_FUNC_INFO << "Drop trigger:" + << query.lastError().text() << ":" << query.lastError().databaseText(); + ok = false; + } + if (!query.exec(DROP_METADATA)) { + qWarning() << Q_FUNC_INFO << "Drop metadata:" + << query.lastError().text() << ":" << query.lastError().databaseText(); + ok = false; + } + if (!query.exec(DROP_CALLBACK)) { + qWarning() << Q_FUNC_INFO << "Drop callback:" + << query.lastError().text() << ":" << query.lastError().databaseText(); + ok = false; + } + if (!query.exec(DROP_TRANSFERS)) { + qWarning() << Q_FUNC_INFO << "Drop transfers:" + << query.lastError().text() << ":" << query.lastError().databaseText(); + ok = false; + } + + query.finish(); + return ok; + } + + int userVersion() + { + const QString queryStr = QString("PRAGMA user_version"); + + QSqlQuery query; + if (!query.exec(queryStr)) { + qWarning() << "DbManager::callback: Failed to execute SQL query. Couldn't update the progress!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + return -1; + } + QSqlRecord rec = query.record(); + if (query.isActive() && query.isSelect()) { + query.first(); + QString v = query.value(rec.indexOf("user_version")).toString(); + if (v.isEmpty()) { + return -1; + } + return v.toInt(); + } + return -1; + } + + QSqlDatabase m_db; +}; + +/*! \class DbManager + \brief The DbManager class is a singleton class to read and write transfers database. + + \ingroup transfer-engine + + DbManager class takes care of reading and writing transfer database used by Nemo Transfer + Engine. It's a singleton class and it can be instantiated using DbManager::instance() method. +*/ + + +/*! + Returns a singleton instance of this DbManager. Note that caller is NOT responsible of + deleting the instance. It will be deleted automatically when application stack is cleaned. + */ +DbManager * DbManager::instance() +{ + static DbManager instance; + return &instance; +} + +/*! + Private constructor. + */ +DbManager::DbManager(): + d_ptr(new DbManagerPrivate) +{ + Q_D(DbManager); + const QString absDbPath = QDir::homePath() + QDir::separator() + + DB_PATH + QDir::separator() + + DB_NAME; + + bool dbExists = QFile::exists(absDbPath); + + if (!dbExists) { + if (!QDir().mkpath(QDir::homePath() + QDir::separator() + DB_PATH)) { + qWarning() << "DbManager::DbManager: failed to create directory for db!"; + return; + } + } + + d->m_db = QSqlDatabase::addDatabase("QSQLITE"); + d->m_db.setDatabaseName(absDbPath); + d->m_db.setConnectOptions("foreign_keys = ON"); // sanity check + d->m_db.open(); + + // Create database schema if db didn't exist + if (!dbExists) { + if(!d->createDatabaseSchema()) { + qCritical("DbManager::DbManager: Failed to create DB schema. Can't continue!"); + } + } else { + // Database exists, check the schema version + if (d->userVersion() != USER_VERSION) { + d->deleteOldTables(); + d->createDatabaseSchema(); + } + } + + TransferDBRecord::registerType(); +} + +/*! + Destroys the DbManager. Clients should not call this, instead the created DbManager instance + will be destroyed automatically. + */ +DbManager::~DbManager() +{ + Q_D(DbManager); + if (d->m_db.isOpen()) { + d->m_db.close(); + } + + delete d_ptr; + d_ptr = 0; +} + +/*! + Returns a DBus callback interface and method names for the transfer with \a key. + If there is no callback for the \a key then an empty QStringList is returned. + + In a case there is a DBus callback, then QStringList contains the following items: + \list + \o service + \o path + \o interface + \o cancel method name + \o restart method name + \endlist + */ +QStringList DbManager::callback(int key) const +{ + QString queryStr = QString("SELECT service, path, interface, cancel_method, restart_method FROM callback WHERE transfer_id='%1';") + .arg(QString::number(key)); + + QStringList result; + QSqlQuery query; + if (!query.exec(queryStr)) { + qWarning() << "DbManager::callback: Failed to execute SQL query. Couldn't update the progress!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + return result; + } + + QSqlRecord rec = query.record(); + if (query.isActive() && query.isSelect()) { + query.first(); + result << query.value(rec.indexOf("service")).toString() + << query.value(rec.indexOf("path")).toString() + << query.value(rec.indexOf("interface")).toString() + << query.value(rec.indexOf("cancel_method")).toString() + << query.value(rec.indexOf("restart_method")).toString(); + } + return result; +} + +/*! + Creates a metadata entry for the existing transfer with \a key. Metadata can contain only + \a title and/or \a description. + + Metadata entry will be created to the metadata table. Argument \a key must point to the + existing entry in transfers table. + + This method returns a key of the created record in metadata table or -1 on failure. + + NOTE: Deleting the record from the transfer which has a \a key, also deletes related + metadata entry. + */ +int DbManager::createMetadataEntry(int key, const QString &title, const QString &description) +{ + QSqlQuery query; + query.prepare("INSERT INTO metadata (title, description, transfer_id)" + "VALUES (:title, :description, :transfer_id)"); + query.bindValue(":title", title); + query.bindValue(":description", description); + query.bindValue(":transfer_id", key); + + if (!query.exec()) { + qWarning() << "DbManager::createMetadataEntry: Failed to execute SQL query. Couldn't create an entry!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + return -1; + } + + // Return the id of the last record + QVariant rowId = query.lastInsertId(); + query.finish(); + return rowId.isValid()? rowId.toInt() : -1; +} + +/*! + Creates a callback entry to the callback table for the existing transfer with a \a key. + + The callback is a dbus interface so it must contain the following attributes: + \list + \o \a service e.g. com.jolla.myapp + \o \a path e.g. /com/jolla/myapp + \o \a interface e.g. com.jolla.myapp + \o \a cancelMethod The name of the cancel method + \o \a restartMethod The name of the restart method + \endlist + + This method returns a key of the created callback record in a callback table or -1 on + failure. + + NOTE: Deleting the record from the transfer which has a \a key, also deletes related + callback entry. + + */ +int DbManager::createCallbackEntry(int key, + const QString &service, + const QString &path, + const QString &interface, + const QString &cancelMethod, + const QString &restartMethod) +{ + QSqlQuery query; + query.prepare("INSERT INTO callback (service, path, interface, cancel_method, restart_method, transfer_id)" + "VALUES (:service, :path, :interface, :cancel_method, :restart_method, :transfer_id)"); + query.bindValue(":service", service); + query.bindValue(":path", path); + query.bindValue(":interface", interface); + query.bindValue(":cancel_method", cancelMethod); + query.bindValue(":restart_method", restartMethod); + query.bindValue(":transfer_id", key); + + if (!query.exec()) { + qWarning() << "DbManager::createCallbackEntry: Failed to execute SQL query. Couldn't create an entry!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + return -1; + } + + // Return the id of the last record + QVariant rowId = query.lastInsertId(); + query.finish(); + return rowId.isValid()? rowId.toInt() : -1; +} + +/*! + Creates a transfer entry to the transfers table bsaed on \a mediaItem content. + + MediaItem instance contains all the required information for the single Upload, + Download or a Sync item. Based on this information, DbManager creates a record + to the transfers table, but also to the callback and metadata tables if these + are defined. + + This method returns a key of the created transfer or -1 on failure. +*/ +int DbManager::createTransferEntry(MediaItem *mediaItem) +{ + Q_D(DbManager); + QSqlQuery query; + query.prepare("INSERT INTO transfers (transfer_type, timestamp, status, progress, display_name, application_icon, thumbnail_icon, " + "service_icon, url, resource_name, mime_type, file_size, plugin_id, account_id, strip_metadata, scale_percent, cancel_supported, restart_supported)" + "VALUES (:transfer_type, :timestamp, :status, :progress, :display_name, :application_icon, :thumbnail_icon, :service_icon, " + ":url, :resource_name, :mime_type, :file_size, :plugin_id, :account_id, :strip_metadata, :scale_percent, :cancel_supported, :restart_supported)"); + query.bindValue(":transfer_type", mediaItem->value(MediaItem::TransferType)); + query.bindValue(":status", TransferEngineData::NotStarted); + query.bindValue(":timestamp", d->currentDateTime()); + query.bindValue(":progress", 0); + query.bindValue(":display_name", mediaItem->value(MediaItem::DisplayName)); + query.bindValue(":application_icon", mediaItem->value(MediaItem::ApplicationIcon)); + query.bindValue(":thumbnail_icon", mediaItem->value(MediaItem::ThumbnailIcon)); + query.bindValue(":service_icon", mediaItem->value(MediaItem::ServiceIcon)); + query.bindValue(":url", mediaItem->value(MediaItem::Url)); + query.bindValue(":resource_name", mediaItem->value(MediaItem::ResourceName)); + query.bindValue(":mime_type", mediaItem->value(MediaItem::MimeType)); + query.bindValue(":file_size", mediaItem->value(MediaItem::FileSize)); + query.bindValue(":plugin_id", mediaItem->value(MediaItem::PluginId)); + query.bindValue(":account_id", mediaItem->value(MediaItem::AccountId)); + query.bindValue(":strip_metadata", mediaItem->value(MediaItem::MetadataStripped)); + query.bindValue(":scale_percent", mediaItem->value(MediaItem::ScalePercent)); + query.bindValue(":cancel_supported", mediaItem->value(MediaItem::CancelSupported)); + query.bindValue(":restart_supported", mediaItem->value(MediaItem::RestartSupported)); + + if (!query.exec()) { + qWarning() << "DbManager::createTransfereEntry: Failed to execute SQL query. Couldn't create an entry!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + return -1; + } + + // Return the id of the last record + QVariant rowId = query.lastInsertId(); + query.finish(); + + if (!rowId.isValid()) { + qWarning() << "DbManager::createShareEntry: Invalid row ID!"; + return -1; + } + + // Create a metadata entry if user has passed any + const QString title = mediaItem->value(MediaItem::Title).toString(); + const QString desc = mediaItem->value(MediaItem::Description).toString(); + if (!title.isEmpty() && !desc.isEmpty()) { + if (createMetadataEntry(rowId.toInt(), title, desc) < 0){ + qWarning() << "DbManager::createTransferEntry: Failed to create metadata entry"; + return -1; + } + } + + // Create a callback entry if it's been provided + const QStringList callback = mediaItem->value(MediaItem::Callback).toStringList(); + const QString cancelMethod = mediaItem->value(MediaItem::CancelCBMethod).toString(); + const QString restartMethod = mediaItem->value(MediaItem::RestartCBMethod).toString(); + + // One of the methods must exist if the callback has been provided + if (callback.count() == 3 && (!cancelMethod.isEmpty() || !restartMethod.isEmpty())){ + const int res = createCallbackEntry(rowId.toInt(), callback.at(0), callback.at(1), callback.at(2), + cancelMethod, restartMethod); + if (res < 0) { + qWarning() << "DbManager::createTransferEntry: Failed to create callback entry"; + return -1; + } + } + + return rowId.toInt(); +} + +/*! + Updates transfer \a status of the existing transfer with \a key. Changing the status updates + the timestamp too. + + This method returns true on success, false on failure. + */ +bool DbManager::updateTransferStatus(int key, TransferEngineData::TransferStatus status) +{ + Q_D(DbManager); + QString queryStr; + switch(status) { + case TransferEngineData::TransferStarted: + queryStr = QString("UPDATE transfers SET status='%1', progress='0', timestamp='%2' WHERE transfer_id='%3';") + .arg(QString::number(status)) + .arg(d->currentDateTime()) + .arg(QString::number(key)); + break; + + case TransferEngineData::NotStarted: + case TransferEngineData::TransferFinished: + case TransferEngineData::TransferInterrupted: + case TransferEngineData::TransferCanceled: + queryStr = QString("UPDATE transfers SET status='%1', timestamp='%2' WHERE transfer_id='%3';") + .arg(QString::number(status)) + .arg(d->currentDateTime()) + .arg(QString::number(key)); + break; + case TransferEngineData::Unknown: + qWarning() << "Unknown transfer status!"; + return false; + } + + QSqlQuery query; + if (!query.exec(queryStr)) { + qWarning() << "Failed to execute SQL query. Couldn't update a record!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + return false; + } + query.finish(); + return true; +} + +/*! + Updates transfer \a progress of the existing transfer with \a key. + + This method returns true on success, false on failure. + */ +bool DbManager::updateProgress(int key, qreal progress) +{ + QString queryStr = QString("UPDATE transfers SET progress='%1' WHERE transfer_id='%2';") + .arg(QString::number(progress)) + .arg(QString::number(key)); + + QSqlQuery query; + if (!query.exec(queryStr)) { + qWarning() << "Failed to execute SQL query. Couldn't update the progress!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + return false; + } + query.finish(); + return true; +} + +/*! + Removes an existing transfer with a \a key from the transfers table. If this transfer has + metadata or callback defined, they will be removed too. + + This method returns true on success, false on failure. + */ +bool DbManager::removeTransfer(int key) +{ + QString queryStr = QString("DELETE FROM transfers WHERE transfer_id='%1' AND (status='%2' OR status='%3' OR status='%4');") + .arg(key) + .arg(TransferEngineData::TransferFinished) + .arg(TransferEngineData::TransferCanceled) + .arg(TransferEngineData::TransferInterrupted); + + QSqlQuery query; + if (!query.exec(queryStr)) { + qWarning() << "Failed to execute SQL query. Couldn't delete the transfer with key " << key; + return false; + } + + query.finish(); + return true; +} + +/*! + Clears all finished, canceled or failed transfers from the database. + + This method returns true on success, false on failure. +*/ +bool DbManager::clearTransfers() +{ + QString queryStr = QString("DELETE FROM transfers WHERE status='%1' OR status='%2' OR status='%3';") + .arg(TransferEngineData::TransferFinished) + .arg(TransferEngineData::TransferCanceled) + .arg(TransferEngineData::TransferInterrupted); + + QSqlQuery query; + if (!query.exec(queryStr)) { + qWarning() << "Failed to execute SQL query. Couldn't delete the list finished transfers!"; + return false; + } + + query.finish(); + return true; +} + +/*! + Returns all the transfers from the database. This method doesn't fetch all the fields from all the + tables, instead it returns what is required to fill fields in TransferDBRecord class. + */ +QList DbManager::transfers() const +{ + // TODO: This should order the result based on timestamp + QList records; + QSqlQuery query; + if (!query.exec("SELECT * FROM transfers ORDER BY transfer_id DESC")) { + qWarning() << "DbManager::transfers: Failed to execute SQL query. Couldn't get list of transfers!"; + return records; + } + + // The record could actually contain eg. QVariantList instead of hardcoded and + // typed members. + QSqlRecord rec = query.record(); + while (query.next()) { + TransferDBRecord record; + record.transfer_id = query.value(rec.indexOf("transfer_id")).toInt(); + record.transfer_type = query.value(rec.indexOf("transfer_type")).toInt(); + record.progress = query.value(rec.indexOf("progress")).toDouble(); + record.url = query.value(rec.indexOf("url")).toString(); + record.status = query.value(rec.indexOf("status")).toInt(); + record.plugin_id = query.value(rec.indexOf("plugin_id")).toString(); + record.display_name = query.value(rec.indexOf("display_name")).toString(); + record.resource_name = query.value(rec.indexOf("resource_name")).toString(); + record.mime_type = query.value(rec.indexOf("mime_type")).toString(); + record.timestamp = query.value(rec.indexOf("timestamp")).toString(); + record.size = query.value(rec.indexOf("file_size")).toInt(); + record.application_icon = query.value(rec.indexOf("application_icon")).toString(); + record.thumbnail_icon = query.value(rec.indexOf("thumbnail_icon")).toString(); + record.service_icon = query.value(rec.indexOf("service_icon")).toString(); + record.cancel_supported = query.value(rec.indexOf("cancel_supported")).toBool(); + record.restart_supported = query.value(rec.indexOf("restart_supported")).toBool(); + records << record; + } + query.finish(); + return records; +} + +/*! + Returns the transfer type e.g. Sync, Download or Upload of the transfer with a \a key. + + If there is no transfer record with key or error occurs, this method returns TransferEngineData::Undefined. + */ +TransferEngineData::TransferType DbManager::transferType(int key) const +{ + QString queryStr = QString("SELECT transfer_type FROM transfers WHERE transfer_id='%1';") + .arg(QString::number(key)); + + QSqlQuery query; + if (!query.exec(queryStr)) { + qWarning() << "DbManager::transferType: Failed to execute SQL query. Couldn't update the progress!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + return TransferEngineData::Undefined; + } + + + if (query.isActive() && query.isSelect()) { + query.first(); + return static_cast(query.value(0).toInt()); + } else { + return TransferEngineData::Undefined; + } +} + +/*! + Returns the transfer status of the transfer with \a key. In a case of error + the TransferEngineData::Unknown is returned. + */ +TransferEngineData::TransferStatus DbManager::transferStatus(int key) const +{ + + QString queryStr = QString("SELECT status FROM transfers WHERE transfer_id='%1';") + .arg(QString::number(key)); + + QSqlQuery query; + if (!query.exec(queryStr)) { + qWarning() << "DbManager::transferStatus: Failed to execute SQL query. Couldn't update the progress!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + return TransferEngineData::Unknown; + } + + + if (query.isActive() && query.isSelect()) { + query.first(); + return static_cast(query.value(0).toInt()); + } else { + return TransferEngineData::Unknown; + } +} +/*! + Reads the callback method names from the database for the transfer with \a key. The method names are set to the + output arguments \a cancelMethod and \a restartMethod. + + This method returns true on success, false on failure. +*/ +bool DbManager::callbackMethods(int key, QString &cancelMethod, QString &restartMethod) const +{ + QString queryStr = QString("SELECT cancel_method, restart_method FROM callback WHERE transfer_id='%1';") + .arg(QString::number(key)); + + QSqlQuery query; + if (!query.exec(queryStr)) { + qWarning() << "DbManager::callbackMethods: Failed to execute SQL query. Couldn't get callback methods!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + return false; + } + + + if (query.isActive() && query.isSelect()) { + query.first(); + cancelMethod = query.value(0).toString(); + restartMethod = query.value(1).toString(); + return true; + } else { + return false; + } +} + +// Used only for Sharing atm. If this is needed for Sync and download add fetching the callback too. +/*! + Returns a MediaItem instance from the transfer data with a \a key. +*/ +MediaItem * DbManager::mediaItem(int key) const +{ + QString queryStr = QString("SELECT * FROM transfers WHERE transfer_id='%1';") + .arg(QString::number(key)); + + QSqlQuery query; + if (!query.exec(queryStr)) { + qWarning() << "DbManager::mediaItem: Failed to execute SQL query. Couldn't update the progress!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + return 0; + } + + MediaItem *item = new MediaItem; + QSqlRecord rec = query.record(); + if (query.next()) { + item->setValue(MediaItem::Url, query.value(rec.indexOf("url"))); + item->setValue(MediaItem::MetadataStripped,query.value(rec.indexOf("strip_metadata"))); + item->setValue(MediaItem::ScalePercent, query.value(rec.indexOf("scale_percent"))); + item->setValue(MediaItem::ResourceName, query.value(rec.indexOf("resource_name"))); + item->setValue(MediaItem::MimeType, query.value(rec.indexOf("mime_type"))); + item->setValue(MediaItem::TransferType, query.value(rec.indexOf("transfer_type"))); + item->setValue(MediaItem::FileSize, query.value(rec.indexOf("file_size"))); + item->setValue(MediaItem::PluginId, query.value(rec.indexOf("plugin_id"))); + item->setValue(MediaItem::AccountId, query.value(rec.indexOf("account_id"))); + item->setValue(MediaItem::DisplayName, query.value(rec.indexOf("display_name"))); + item->setValue(MediaItem::ServiceIcon, query.value(rec.indexOf("service_icon"))); + } else { + qWarning() << "DbManager::mediaItem: Failed to get media item data from database!"; + delete item; + return 0; + } + + query.finish(); + + // Get metadata part title, description + queryStr = QString("SELECT title, description FROM metadata WHERE transfer_id='%1';") + .arg(QString::number(key)); + + if (!query.exec(queryStr)) { + qWarning() << "DbManager::mediaItem: Failed to execute SQL query. Couldn't update the progress!" + << query.lastError().text() << ": " + << query.lastError().databaseText(); + delete item; + return 0; + } + rec = query.record(); + // NOTE: There might be that user hasn't set any title or description so let the flow just pass + // this point if there isn't anything... + if (query.next()) { + item->setValue(MediaItem::Title, query.value(rec.indexOf("title"))); + item->setValue(MediaItem::Title, query.value(rec.indexOf("description"))); + } + + query.finish(); + return item; +} + + + + diff --git a/src/dbmanager.h b/src/dbmanager.h new file mode 100644 index 0000000..bdbd63b --- /dev/null +++ b/src/dbmanager.h @@ -0,0 +1,80 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef DBMANAGER_H +#define DBMANAGER_H +#include + +#include "transferdbrecord.h" +#include "mediatransferinterface.h" + +class MediaItem; +class DbManagerPrivate; +class DbManager +{ +public: + static DbManager *instance(); + + ~DbManager(); + + int createMetadataEntry(int key, const QString &title, const QString &description); + + QStringList callback(int key) const; + + int createCallbackEntry(int key, + const QString &service, + const QString &path, + const QString &interface, + const QString &cancelMethod, + const QString &restartMethod); + + int createTransferEntry(MediaItem *mediaItem); + + bool updateTransferStatus(int key, TransferEngineData::TransferStatus status); + + bool updateProgress(int key, qreal progress); + + bool removeTransfer(int key); + + bool clearTransfers(); + + QList transfers() const; + + TransferEngineData::TransferType transferType(int key) const; + + TransferEngineData::TransferStatus transferStatus(int key) const; + + bool callbackMethods(int key, QString &cancelMethod, QString &restartMethod) const; + + MediaItem * mediaItem(int key) const; + +private: + DbManager(); + DbManagerPrivate *d_ptr; + Q_DECLARE_PRIVATE(DbManager) +}; + +#endif // DBMANAGER_H diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..bca8c5f --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include +#include +#include +#include "transferengine.h" + + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + QCoreApplication::setOrganizationName("nemomobile"); + QCoreApplication::setApplicationName("nemo-transfer-engine"); + + QString translationPath("/usr/share/translations/"); + QTranslator engineeringEnglish; + engineeringEnglish.load("nemo-transfer-engine_eng_en", translationPath); + qApp->installTranslator(&engineeringEnglish); + + QTranslator translator; + translator.load(QLocale(), "nemo-transfer-engine", "-", translationPath); + app.installTranslator(&translator); + + + TransferEngine engine; + return app.exec(); +} diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 0000000..24c9677 --- /dev/null +++ b/src/src.pro @@ -0,0 +1,68 @@ +TEMPLATE = app +TARGET = nemo-transfer-engine +DEPENDPATH += . +INCLUDEPATH += . ../lib + +QT += dbus sql + +LIBS += -L../lib -lnemotransferengine + +# generate adaptor code +system(qdbusxml2cpp -c TransferEngineAdaptor -a transferengineadaptor.h:transferengineadaptor.cpp -i metatypedeclarations.h ../dbus/org.nemo.transferengine.xml) + +CONFIG += link_pkgconfig +PKGCONFIG += mlite +PKGCONFIG += accounts-qt + +# translations +TS_FILE = $$OUT_PWD/nemo-transfer-engine.ts +EE_QM = $$OUT_PWD/nemo-transfer-engine_eng_en.qm + +ts.commands += lupdate $$PWD -ts $$TS_FILE +ts.CONFIG += no_check_exist +ts.output = $$TS_FILE +ts.input = . + +ts_install.files = $$TS_FILE +ts_install.path = /usr/share/translations/source +ts_install.CONFIG += no_check_exist + +# should add -markuntranslated "-" when proper translations are in place (or for testing) +engineering_english.commands += lrelease -idbased $$TS_FILE -qm $$EE_QM +engineering_english.CONFIG += no_check_exist +engineering_english.depends = ts +engineering_english.input = $$TS_FILE +engineering_english.output = $$EE_QM + +engineering_english_install.path = /usr/share/translations +engineering_english_install.files = $$EE_QM +engineering_english_install.CONFIG += no_check_exist + +QMAKE_EXTRA_TARGETS += ts engineering_english + +PRE_TARGETDEPS += ts engineering_english + +# Input +SOURCES += main.cpp \ + transferengineadaptor.cpp \ + dbmanager.cpp \ + transferengine.cpp + +HEADERS += \ + transferengineadaptor.h \ + dbmanager.h \ + transferengine.h \ + transferengine_p.h + +SERVICE_FILE += ../dbus/org.nemo.transferengine.service +OTHER_FILES += $$SERVICE_FILE \ + ../dbus/org.nemo.transferengine.xml + + +service.files = $$SERVICE_FILE +service.path = /usr/share/dbus-1/services/ +target.path = /usr/bin + +INSTALLS += service target ts_install engineering_english_install + + diff --git a/src/transferengine.cpp b/src/transferengine.cpp new file mode 100644 index 0000000..8af11c3 --- /dev/null +++ b/src/transferengine.cpp @@ -0,0 +1,1170 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include "transferengine.h" +#include "transferengine_p.h" +#include "transferplugininterface.h" +#include "mediaitem.h" +#include "dbmanager.h" +#include "transferengineadaptor.h" +#include "transfertypes.h" +#include "transferplugininfo.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define SHARE_PLUGINS_PATH "/usr/lib/nemo-transferengine/plugins" +#define FILE_WATCHER_TIMEOUT 5000 + + +TransferEngineSignalHandler * TransferEngineSignalHandler::instance() +{ + static TransferEngineSignalHandler instance; + return &instance; +} + +void TransferEngineSignalHandler::signalHandler(int signal) +{ + if(signal == SIGUSR1) { + QMetaObject::invokeMethod(TransferEngineSignalHandler::instance(), + "exitSafely", + Qt::AutoConnection); + } +} + +TransferEngineSignalHandler::TransferEngineSignalHandler() +{ + signal(SIGUSR1, TransferEngineSignalHandler::signalHandler); +} + + +// ---------------------------- + +TransferEnginePrivate::TransferEnginePrivate(TransferEngine *parent): + m_notificationsEnabled(true), + q_ptr(parent) +{ + m_fileWatcherTimer = new QTimer(this); + m_fileWatcherTimer->setSingleShot(true); + connect(m_fileWatcherTimer, SIGNAL(timeout()), this, SLOT(enabledPluginsCheck())); + + m_fileWatcher = new QFileSystemWatcher(this); + m_fileWatcher->addPath(SHARE_PLUGINS_PATH); + connect(m_fileWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(pluginDirChanged())); + + m_accountManager = new Accounts::Manager("sharing", this); + connect(m_accountManager, SIGNAL(accountCreated(Accounts::AccountId)), this, SLOT(enabledPluginsCheck())); + connect(m_accountManager, SIGNAL(accountRemoved(Accounts::AccountId)), this, SLOT(enabledPluginsCheck())); + connect(m_accountManager, SIGNAL(accountUpdated(Accounts::AccountId)), this, SLOT(enabledPluginsCheck())); + connect(m_accountManager, SIGNAL(enabledEvent(Accounts::AccountId)), this, SLOT(enabledPluginsCheck())); + + m_transfersInProgressCount = 0; + connect(TransferEngineSignalHandler::instance(), SIGNAL(exitSafely()), this, SLOT(exitSafely())); + Q_Q(TransferEngine); + connect(q, SIGNAL(statusChanged(int,int)), this, SLOT(inProgressTransfersCheck())); +} + +void TransferEnginePrivate::pluginDirChanged() +{ + // We need to check our plugins, but only after a short period of time + // because some operations may cause calling this slot over 10 times. + // E.g. reinstallation of plugins from the RPM package + m_fileWatcherTimer->start(FILE_WATCHER_TIMEOUT); +} + +void TransferEnginePrivate::exitSafely() +{ + if (m_transfersInProgressCount == 0) { + qDebug() << Q_FUNC_INFO; + qApp->exit(); + } +} + +void TransferEnginePrivate::inProgressTransfersCheck() +{ + int count = 0; + // Just read the statuses from the DB. + QList records = DbManager::instance()->transfers(); + Q_FOREACH(TransferDBRecord record, records) { + if (record.status == TransferEngineData::TransferStarted || + record.status == TransferEngineData::NotStarted) { + ++count; + } + } + m_transfersInProgressCount = count; + if (m_transfersInProgressCount == 0) { + qApp->exit(); + } +} + +void TransferEnginePrivate::enabledPluginsCheck() +{ + Q_Q(TransferEngine); + if (m_fileWatcherTimer->isActive()) { + m_fileWatcherTimer->stop(); + } + + // First clear old data + m_enabledPlugins.clear(); + qDeleteAll(m_infoObjects); + m_infoObjects.clear(); + + QPluginLoader loader; + loader.setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint); + + // Handle the case if all the plugins have been removed. + QStringList plugins = pluginList(); + if (plugins.isEmpty()) { + emit q->transferMethodListChanged(); + return; + } + + // We have plugins + Q_FOREACH(QString plugin, plugins) { + loader.setFileName(plugin); + TransferPluginInterface *interface = + qobject_cast(loader.instance()); + + if (interface && interface->enabled()) { + + TransferPluginInfo *info = interface->infoObject(); + if (!info) { + qWarning() << Q_FUNC_INFO << "NULL Info object!"; + continue; + } + + // Put info object to temporary container to wait that query result + // is returned. These object will be cleaned in pluginInfoReady() slot. + m_infoObjects << info; + connect(info, SIGNAL(infoReady()), this, SLOT(pluginInfoReady())); + connect(info, SIGNAL(infoError(QString)), this, SLOT(pluginInfoError(QString))); + info->query(); + } + + if (!interface) { + qWarning() << Q_FUNC_INFO << loader.errorString(); + } + } + + +} + +void TransferEnginePrivate::recoveryCheck() +{ + QList records = DbManager::instance()->transfers(); + // Check all transfer which are not properly finished and mark those as + // interrupted + Q_FOREACH(TransferDBRecord record, records) { + if (record.status == TransferEngineData::TransferStarted || + record.status == TransferEngineData::NotStarted) { + DbManager::instance()->updateTransferStatus(record.transfer_id, TransferEngineData::TransferInterrupted); + } + } +} + +void TransferEnginePrivate::sendNotification(TransferEngineData::TransferType type, + TransferEngineData::TransferStatus status, + const QUrl &url) +{ + if (!m_notificationsEnabled || !url.isValid()) { + return; + } + + QStringList split; + QString fileName; + + if (type != TransferEngineData::Sync) { + split = url.toString().split(QDir::separator()); + fileName = split.at(split.length()-1); + } + + QString msgGSummary; + QString msgNBody; + QString eventType; + bool bannerOnly = false; + + if (status == TransferEngineData::TransferFinished) { + switch(type) { + case TransferEngineData::Upload: + //: Notification for successful file upload + //% "File uploaded" + msgNBody = qtTrId("transferengine-no-file-upload-success"); + msgGSummary.clear(); + eventType = MNotification::TransferEvent; // Use "generic" transfer event for uploads + bannerOnly = true; + break; + case TransferEngineData::Download: + //: Notification for successful file download + //% "File downloaded" + msgNBody = qtTrId("transferengine-no-file-download-success"); + //: NotificationGroup summary for successful download + //% "%1 file(s) downloaded" + msgGSummary = qtTrId("%1 file(s) downloaded"); + eventType = MNotification::TransferCompleteEvent; + break; + case TransferEngineData::Sync: + // Ok exit + return; + default: + qWarning() << "TransferEnginePrivate::sendNotification: unknown state"; + return; + } + } else { + if (status == TransferEngineData::TransferInterrupted) { + switch (type) { + case TransferEngineData::Upload: + //: Notification for failed file upload + //% "Upload failed!" + msgNBody = qtTrId("transferengine-no-file-upload-failure"); + //% "%1 upload(s) failed" + msgGSummary = qtTrId("%1 file upload(s) failed"); + break; + case TransferEngineData::Download: + //: Notification for successful file download + //% "Download failed!" + msgNBody = qtTrId("transferengine-no-file-download-failure"); + //% "%1 download(s) failed" + msgGSummary = qtTrId("%1 download(s) failed"); + break; + case TransferEngineData::Sync: + //: Notification for sync failure + //% "Sync failed!" + msgNBody = qtTrId("transferengine-no-sync-failure"); + //% "%1 sync(s) failed" + msgGSummary = qtTrId("%1 sync(s) failed"); + break; + default: + qWarning() << "TransferEnginePrivate::sendNotification: unknown state"; + return; + } + + eventType = MNotification::TransferErrorEvent; + } else { + if (status == TransferEngineData::TransferCanceled) { + // Exit, no banners or events when user has canceled a transfer + return; + }}} + + // Notification & Banner rules: + // + // Show Banner: + // - For succesfull uploads and for downloads + // - For failed Uploads, Downloads, Syncs + // + // Show an event in the EventView: + // - For downloads + // - For failed uploads, downloads and syncs + // + // Use grouping always + // + // TODO: Add MRemoteAction for e.g. opening a file. + // - Open a file, when there is only a one notification in that group + // - Open The Settings with Transfer UI when there are more than one notifications + if (!(msgNBody.isEmpty() && eventType.isEmpty())) { + // First create the notification + MNotification notification(eventType); + notification.setSummary(fileName); + notification.setBody(msgNBody); + notification.setImage("icon-l-share"); + + QList nList = MNotification::notifications(); + QMultiMap nMap; + + // Get the existing notifications and sort them based on their event types + foreach(MNotification *n, nList) { + nMap.insert(n->eventType(), n); + } + + // Get the number of existing events of this same type + this event + const int eventCount = nMap.values(eventType).count() + 1; + + // Check if we have existing group and use that instead of creating a new one. + QList groups = MNotificationGroup::notificationGroups(); + MNotificationGroup *group = 0; + if (groups.count() > 0) { + foreach(MNotificationGroup *g, groups) { + if (g->eventType() == eventType) { + group = g; + break; + } + } + } + + // No existing groups, create a new one from the scratch + if (group == 0){ + group = new MNotificationGroup(eventType); + group->setImage("icon-l-share"); + // Add to the groups, it will be deleted when the list is cleaned + groups.append(group); + } + + if (bannerOnly) { + // This makes notifications to appear banners only + group->setSummary(QString()); + } else { + // This is the summary text which is shown when notifications are grouped + group->setSummary(msgGSummary.arg(eventCount)); + group->setBody(fileName); + } + + // Set default action for groups + MRemoteAction rAct = createRemoteActionForGroup(); + if (!rAct.toString().isEmpty()) { + group->setAction(rAct); + } + + // always publish the group to make updates appear + group->publish(); + + notification.setGroup(*group); + notification.publish(); + + // Cleanup + if (groups.count()) { + qDeleteAll(groups); + } + + if (nList.count()) { + qDeleteAll(nList); + } + } +} + +int TransferEnginePrivate::uploadMediaItem(MediaItem *mediaItem, + MediaTransferInterface *muif, + const QVariantMap &userData) +{ + Q_Q(TransferEngine); + + if (muif == 0) { + qWarning() << "TransferEngine::uploadMediaItem invalid MediaItem"; + return -1; + } + if (muif == 0) { + qWarning() << "TransferEngine::uploadMediaItem Failed to get MediaTransferInterface"; + return -1; + } + + mediaItem->setValue(MediaItem::TransferType, TransferEngineData::Upload); + mediaItem->setValue(MediaItem::DisplayName, muif->displayName()); + mediaItem->setValue(MediaItem::ServiceIcon, muif->serviceIcon()); + mediaItem->setValue(MediaItem::CancelSupported, muif->cancelEnabled()); + mediaItem->setValue(MediaItem::RestartSupported, muif->restartEnabled()); + + // Get and set data from user data if that's set. The following user data values + // are stored to the database so that's why they are set to the media item too. + // If the user data is fully custom for plugin it won't be stored to the database and + // it's up to the plugin to handle or ignore it. + QString title = userData.value("title").toString(); + QString desc = userData.value("description").toString(); + qint64 accId = userData.value("accountId").toInt(); + qreal scale = userData.value("scalePercent").toReal(); + + mediaItem->setValue(MediaItem::Title, title); + mediaItem->setValue(MediaItem::Description, desc); + mediaItem->setValue(MediaItem::AccountId, accId); + mediaItem->setValue(MediaItem::ScalePercent, scale); + muif->setMediaItem(mediaItem); + + connect(muif, SIGNAL(statusChanged(MediaTransferInterface::TransferStatus)), + this, SLOT(uploadItemStatusChanged(MediaTransferInterface::TransferStatus))); + connect(muif, SIGNAL(progressUpdated(qreal)), + this, SLOT(updateProgress(qreal))); + + // Let's create an entry into Transfer DB + const int key = DbManager::instance()->createTransferEntry(mediaItem); + m_keyTypeCache.insert(key, TransferEngineData::Upload); + + if (key < 0) { + qWarning() << "TransferEngine::uploadMediaItem: Failed to create an entry to transfer database!"; + delete muif; + return key; + } + + emit q->transfersChanged(); + emit q->statusChanged(key, TransferEngineData::NotStarted); + + // For now, we just store our uploader to a map. It'll be removed from it when + // the upload has finished. + m_plugins.insert(muif, key); + muif->start(); + return key; +} + +QStringList TransferEnginePrivate::pluginList() const +{ + QDir dir(SHARE_PLUGINS_PATH); + QStringList plugins = dir.entryList(QStringList() << "*.so", + QDir::Files, + QDir::NoSort); + QStringList filePaths; + Q_FOREACH(QString plugin, plugins) { + filePaths << dir.absolutePath() + QDir::separator() + plugin; + } + + return filePaths; +} + +QList TransferEnginePrivate::enabledPlugins() const +{ + return m_enabledPlugins; +} + + +MediaTransferInterface *TransferEnginePrivate::loadPlugin(const QString &pluginId) const +{ + QPluginLoader loader; + loader.setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint); + Q_FOREACH(QString plugin, pluginList()) { + loader.setFileName(plugin); + TransferPluginInterface *interface = + qobject_cast(loader.instance()); + + + if (interface && interface->enabled() && interface->pluginId() == pluginId) { + return interface->transferObject(); + } + + if (!interface) { + qWarning() << "TransferEngine::loadPlugin: " + loader.errorString(); + } + + if (loader.isLoaded()) { + loader.unload(); + } + } + + return 0; +} + +void TransferEnginePrivate::uploadItemStatusChanged(MediaTransferInterface::TransferStatus status) +{ + MediaTransferInterface *muif = qobject_cast(sender()); + const int key = m_plugins.value(muif); + const QUrl filePath = muif->mediaItem()->value(MediaItem::Url).toString(); + const TransferEngineData::TransferType type = + static_cast(muif->mediaItem()->value(MediaItem::TransferType).toInt()); + + TransferEngineData::TransferStatus tStatus = static_cast(status); + + bool ok = false; + switch(tStatus) { + case TransferEngineData::TransferStarted: + ok = DbManager::instance()->updateTransferStatus(key, tStatus); + break; + + case TransferEngineData::TransferInterrupted: + case TransferEngineData::TransferCanceled: + case TransferEngineData::TransferFinished: + { + // If the flow ends up here, we are not interested in any signals the same object + // might emit. Let's just disconnect them. + muif->disconnect(); + sendNotification(type, tStatus, filePath); + ok = DbManager::instance()->updateTransferStatus(key, tStatus); + if (m_plugins.remove(muif) == 0) { + qWarning() << "TransferEnginePrivate::uploadItemStatusChanged: Failed to remove media upload object from the map!"; + // What to do here.. Let's just delete it.. + } + muif->deleteLater(); + muif = 0; + } break; + + default: + qWarning() << "TransferEnginePrivate::uploadItemStatusChanged: unhandled status: " << tStatus; + break; + } + + if (!ok) { + qWarning() << "TransferEnginePrivate::uploadItemStatusChanged: Failed update share status for the item: " + key; + return; + } + + Q_Q(TransferEngine); + emit q->statusChanged(key, tStatus); +} + +void TransferEnginePrivate::updateProgress(qreal progress) +{ + MediaTransferInterface *muif = qobject_cast(sender()); + const int key = m_plugins.value(muif); + + if (!DbManager::instance()->updateProgress(key, progress)) { + qWarning() << "TransferEnginePrivate::updateProgress: Failed to update progress"; + return; + } + + Q_Q(TransferEngine); + emit q->progressChanged(key, progress); +} + +void TransferEnginePrivate::pluginInfoReady() +{ + TransferPluginInfo *infoObj = qobject_cast(sender()); + m_enabledPlugins << infoObj->info(); + + m_infoObjects.removeOne(infoObj); + delete infoObj; + + if (m_infoObjects.isEmpty()) { + Q_Q(TransferEngine); + emit q->transferMethodListChanged(); + } +} + +void TransferEnginePrivate::pluginInfoError(const QString &msg) +{ + qWarning() << "TransferEnginePrivate::pluginInfoError:" << msg; + TransferPluginInfo *infoObj = qobject_cast(sender()); + m_infoObjects.removeOne(infoObj); + delete infoObj; + + if (m_infoObjects.isEmpty()) { + Q_Q(TransferEngine); + emit q->transferMethodListChanged(); + } +} + + +TransferEngineData::TransferType TransferEnginePrivate::transferType(int transferId) +{ + if (!m_keyTypeCache.contains(transferId)) { + TransferEngineData::TransferType type = DbManager::instance()->transferType(transferId); + m_keyTypeCache.insert(transferId, type); + return type; + } else { + return m_keyTypeCache.value(transferId); + } +} + + +void TransferEnginePrivate::callbackCall(int transferId, CallbackMethodType method) +{ + // Get DBus callback information. Callback list must contain at least + // service, path, interface and one callback method name. Note that even + // if the cancel or restart method is missing, it'll be indicated as an + // empty string. So the list length is always 5. + QStringList callback = DbManager::instance()->callback(transferId); + if (callback.length() != 5) { + qWarning() << "TransferEnginePrivate:callbackCall: Invalid callback interface"; + return; + } + + QDBusInterface remoteInterface(callback.at(Service), + callback.at(Path), + callback.at(Interface)); + + if (!remoteInterface.isValid()) { + qWarning() << "TransferEnginePrivate::callbackCall: DBus interface is not valid!"; + return; + } + + if (method >= callback.size()) { + qWarning() << "TransferEnginePrivate::callbackCall: method index out of range!"; + return; + } + + const QString methodName = callback.at(method); + if (methodName.isEmpty()) { + qWarning() << "TransferEnginePrivate::callbackCall: Failed to get callback method name!"; + return; + } + + remoteInterface.call(methodName, transferId); +} + + +MRemoteAction TransferEnginePrivate::createRemoteActionForGroup() +{ + if (m_settings.status() != QSettings::NoError) { + qWarning() << Q_FUNC_INFO << "Failed to read settings!" << m_settings.status(); + return MRemoteAction(); + } + + m_settings.beginGroup("transfers"); + const QString service = m_settings.value("service").toString(); + const QString path = m_settings.value("path").toString(); + const QString iface = m_settings.value("interface").toString(); + const QString method = m_settings.value("method").toString(); + m_settings.endGroup(); + + return MRemoteAction(service, path, iface, method); +} + +/*! + \class TransferEngine + \brief The TransferEngine class implements the functionality for different transfer types. + + \ingroup transfer-engine + + TransferEngine is the central place for: + \list + \o Sharing - Provides requires plugin interfaces for share plugins + \o Downloads - Provides an API to create Download entries + \o Syncs - Provides an API to create Sync entries + \endlist + + For Downloads and Syncs, the Transfer Engine acts only a place to keep track of these operations. + The actual Download and Sync is executed by a client using TransferEngine API. For sharing + the TransferEngine provides an API containing a few interaces, which a share plugin must implement. + TransferEngine also takes care of loading and executing the sharing, based on the API it defines. + + The most essential thing to remember is that Transfer Engine provides share plugin API, DBus API e.g. + for creating Transfer UI or Share UIs, it stores data to the local sqlite database using DbManager + and that's it. + + How to implement a share plugin see: TransferPluginInterface, MediaTransferInterface, MediaItem, + TransferPluginInfo + + TransferEngine provides DBus API, but instead of using it directly, it's recommended to use + TransferEngineClient. If there is a need to create UI to display e.g. transfer statuses, then + the DBus API is the recommend way to implement it. + + */ + +/*! + \fn void TransferEngine::progressChanged(int transferId, double progress) + + The signal is emitted when \a progress for a transfer with a \a transferId has changed. +*/ + +/*! + \fn void TransferEngine::statusChanged(int transferId, int status) + + The signal is emitted when \a status for a transfer with a \a transferId has changed. +*/ + +/*! + \fn void TransferEngine::transferMethodListChanged() + + The signal is emitted when transfer methods have changed. Usually tranfer methods change + when a new plugin is installed to the system or an account has been enabled or disabled. +*/ + +/*! + \fn void TransferEngine::transfersChanged() + + The signal is emitted when there is a new transfer or a transfer has been removed from the + database. +*/ + +/*! + Constructor with optional \a parent arguement. + */ +TransferEngine::TransferEngine(QObject *parent) : + QObject(parent), + d_ptr(new TransferEnginePrivate(this)) +{ + TransferMethodInfo::registerType(); + TransferDBRecord::registerType(); + + QDBusConnection connection = QDBusConnection::sessionBus(); + if (!connection.registerService("org.nemo.transferengine")) { + qFatal("DBUS service already taken. Kill the other instance first."); + } + + if (!connection.registerObject("/org/nemo/transferengine", this)) { + qFatal("Could not register object \'/org/nemo/transferengine\'"); + } + + + // Let's make sure that db is open by creating + // DbManager singleton instance. + DbManager::instance(); + Q_D(TransferEngine); + d->recoveryCheck(); + d->enabledPluginsCheck(); + + new TransferEngineAdaptor(this); +} + +/*! + Destroys the TransferEngine object. + */ +TransferEngine::~TransferEngine() +{ + Q_D(TransferEngine); + d->recoveryCheck(); + delete d_ptr; + d_ptr = 0; + + QDBusConnection connection = QDBusConnection::sessionBus(); + connection.unregisterObject("/org/nemo/transferengine"); + + if (!connection.unregisterService("org.nemo.transferengine")) { + qWarning() << "Failed to unregister org.nemo.tranferengine service"; + } +} + + +/*! + DBus adaptor calls this method to start uploading a media item. The minimum information + needed to start an upload and to create an entry to the transfer database is: + \a source the path to the media item to be downloaded. \a serviceId the ID of the share + plugin. See TransferPluginInterface::pluginId() for more details. \a mimeType is the MimeType + of the media item e.g. "image/jpeg". \a metadataStripped boolean to indicate if the metadata + should be kept or removed before uploading. \a userData is various kind of data which share UI + may provide to the engine. UserData is QVariant map i.e. the data must be provided as key-value + pairs, where the keys must be QStrings. + + TransferEngine handles the following user defined data automatically and stores them to the database: + \list + \o "title" Title for the media + \o "description" Description for the media + \o "accountId" The ID of the account which is used for sharing. See qt-accounts for more details. + \o "scalePercent" The scale percent e.g. downscale image to 50% from original before uploading. + \endlist + + In practice this method instantiates a share plugin with \a serviceId and passes a MediaItem instance filled + with required data to it. When the plugin has been loaded, the MediaTransferInterface::start() method is called + and the actual sharing starts. + + This method returns a transfer ID which can be used later to fetch information of this specific transfer. + */ +int TransferEngine::uploadMediaItem(const QString &source, + const QString &serviceId, + const QString &mimeType, + bool metadataStripped, + const QVariantMap &userData) +{ + Q_D(TransferEngine); + MediaTransferInterface *muif = d->loadPlugin(serviceId); + if (muif == 0) { + qWarning() << "TransferEngine::uploadMediaItem Failed to get MediaTransferInterface"; + return -1; + } + + QUrl filePath(source); + QFileInfo fileInfo(filePath.toLocalFile()); + if (!fileInfo.exists()) { + qWarning() << "TransferEnginePrivate::uploadMediaItem file " << source << " doesn't exist!"; + } + + MediaItem *mediaItem = new MediaItem(muif); + mediaItem->setValue(MediaItem::Url, filePath); + mediaItem->setValue(MediaItem::MetadataStripped, metadataStripped); + mediaItem->setValue(MediaItem::ResourceName, fileInfo.fileName()); + mediaItem->setValue(MediaItem::MimeType, mimeType); + mediaItem->setValue(MediaItem::FileSize, fileInfo.size()); + mediaItem->setValue(MediaItem::PluginId, serviceId); + mediaItem->setValue(MediaItem::UserData, userData); + return d->uploadMediaItem(mediaItem, muif, userData); +} + +/*! + DBus adaptor calls this method to start uploading media item content. Sometimes the content + to be shared is not a file, but data e.g. contact information in vcard format. In order to + avoid serializing data to a file, pass url to the file, reading the data, deleting the file, + TransferEngine provides this convenience API. + + \a content is the media item content to be shared. \a serviceId is the id of the share plugin. See + TransferPluginInterface::pluginId() for more details. \a userData is a QVariantMap containing + share plugin specific data. See TransferEngine::uploadMediaItem for more details. + + This method returns a transfer ID which can be used later to fetch information of this specific transfer. +*/ +int TransferEngine::uploadMediaItemContent(const QVariantMap &content, + const QString &serviceId, + const QVariantMap &userData) +{ + Q_D(TransferEngine); + MediaTransferInterface *muif = d->loadPlugin(serviceId); + if (muif == 0) { + qWarning() << "TransferEngine::uploadMediaItemContent Failed to get MediaTransferInterface"; + return -1; + } + + MediaItem *mediaItem = new MediaItem(muif); + mediaItem->setValue(MediaItem::ContentData, content.value("data")); + mediaItem->setValue(MediaItem::ResourceName, content.value("name")); + mediaItem->setValue(MediaItem::MimeType, content.value("type")); + mediaItem->setValue(MediaItem::ThumbnailIcon, content.value("icon")); + mediaItem->setValue(MediaItem::PluginId, serviceId); + mediaItem->setValue(MediaItem::UserData, userData); + return d->uploadMediaItem(mediaItem, muif, userData); +} + +/*! + DBus adaptor calls this method to create a download entry. Note that this is purely write-only + method and doesn't involve anything else from TransferEngine side than creating a new DB record + of type 'Download'. + + \list + \o \a displayName The name for Download which may be used by the UI displaying the download + \o \a applicationIcon The application icon of the application created the download + \o \a serviceIcon The service icon, which provides the file to be downloaded + \o \a filePath The filePath e.g. url to the file to be downloaded + \o \a mimeType the MimeType of the file to be downloaded + \o \a expectedFileSize The file size of the file to be downloaded + \o \a callback QStringList containing DBus callback information such as: service, path and interface + \o \a cancelMethod The name of the cancel callback method, which DBus callback provides + \o \a restartMethod The name of the restart callback method, which DBus callback provides + \endlist + + This method returns the transfer id of the created Download transfer. Note that this method only + creates an entry to the database. To start the actual transfer, the startTransfer() method must + be called. + + \sa startTransfer(), restartTransfer(), finishTransfer(), updateTransferProgress() + */ +int TransferEngine::createDownload(const QString &displayName, + const QString &applicationIcon, + const QString &serviceIcon, + const QString &filePath, + const QString &mimeType, + qlonglong expectedFileSize, + const QStringList &callback, + const QString &cancelMethod, + const QString &restartMethod) +{ + Q_D(TransferEngine); + QUrl url(filePath); + QFileInfo fileInfo(filePath); + + MediaItem *mediaItem = new MediaItem(); + mediaItem->setValue(MediaItem::Url, url); + mediaItem->setValue(MediaItem::ResourceName, fileInfo.fileName()); + mediaItem->setValue(MediaItem::MimeType, mimeType); + mediaItem->setValue(MediaItem::TransferType, TransferEngineData::Download); + mediaItem->setValue(MediaItem::FileSize, expectedFileSize); + mediaItem->setValue(MediaItem::DisplayName, displayName); + mediaItem->setValue(MediaItem::ApplicationIcon, applicationIcon); + mediaItem->setValue(MediaItem::ServiceIcon, serviceIcon); + mediaItem->setValue(MediaItem::Callback, callback); + mediaItem->setValue(MediaItem::CancelCBMethod, cancelMethod); + mediaItem->setValue(MediaItem::RestartCBMethod, restartMethod); + mediaItem->setValue(MediaItem::CancelSupported, !cancelMethod.isEmpty()); + mediaItem->setValue(MediaItem::RestartSupported,!restartMethod.isEmpty()); + + const int key = DbManager::instance()->createTransferEntry(mediaItem); + d->m_keyTypeCache.insert(key, TransferEngineData::Download); + emit transfersChanged(); + emit statusChanged(key, TransferEngineData::NotStarted); + return key; +} + +/*! + DBus adaptor calls this method to create a Sync entry. Note that this is purely write-only + method and doesn't involve anything else from TransferEngine side than creating a new DB record + of type 'Download'. + + \list + \o \a displayName The name for download which may be used by the UI displaying the download + \o \a applicationIcon The application icon of the application created the download + \o \a serviceIcon The service icon, which provides the file to be downloaded + \o \a callback QStringList containing DBus callback information such as: service, path and interface + \o \a cancelMethod The name of the cancel callback method, which DBus callback provides + \o \a restartMethod The name of the restart callback method, which DBus callback provides + \endlist + + This method returns the transfer id of the created Download transfer. Note that this method only + creates an entry to the database. To start the actual transfer, the startTransfer() method must + be called. + + \sa startTransfer(), restartTransfer(), finishTransfer(), updateTransferProgress() + */ +int TransferEngine::createSync(const QString &displayName, + const QString &applicationIcon, + const QString &serviceIcon, + const QStringList &callback, + const QString &cancelMethod, + const QString &restartMethod) +{ + MediaItem *mediaItem = new MediaItem(); + mediaItem->setValue(MediaItem::TransferType, TransferEngineData::Sync); + mediaItem->setValue(MediaItem::DisplayName, displayName); + mediaItem->setValue(MediaItem::ApplicationIcon, applicationIcon); + mediaItem->setValue(MediaItem::ServiceIcon, serviceIcon); + mediaItem->setValue(MediaItem::Callback, callback); + mediaItem->setValue(MediaItem::CancelCBMethod, cancelMethod); + mediaItem->setValue(MediaItem::RestartCBMethod, restartMethod); + mediaItem->setValue(MediaItem::CancelSupported, !cancelMethod.isEmpty()); + mediaItem->setValue(MediaItem::RestartSupported,!restartMethod.isEmpty()); + + const int key = DbManager::instance()->createTransferEntry(mediaItem); + Q_D(TransferEngine); + d->m_keyTypeCache.insert(key, TransferEngineData::Sync); + emit transfersChanged(); + emit statusChanged(key, TransferEngineData::NotStarted); + return key; +} + +/*! + DBus adaptor calls this method to start the actual transfer. This method changes the transfer + status of the existing transfer with a \a transferId to TransferEngineData::TransferStarted. This + method can only be called for Sync and Download transfers. + + Calling this method causes the corresponding statusChanged() signal to be emitted. +*/ +void TransferEngine::startTransfer(int transferId) +{ + Q_D(TransferEngine); + TransferEngineData::TransferType type = d->transferType(transferId); + if (type == TransferEngineData::Undefined) { + qWarning() << "TransferEngine::startTransfer: failed to get transfer type"; + return; + } + + if (type == TransferEngineData::Upload) { + qWarning() << "TransferEngine::startTransfer: starting upload isn't supported"; + return; + } + + TransferEngineData::TransferStatus status = DbManager::instance()->transferStatus(transferId); + // First check if this is a new transfer + if (status == TransferEngineData::NotStarted || + status == TransferEngineData::TransferCanceled || + status == TransferEngineData::TransferInterrupted) { + DbManager::instance()->updateTransferStatus(transferId, TransferEngineData::TransferStarted); + emit statusChanged(transferId, TransferEngineData::TransferStarted); + } else { + qWarning() << "TransferEngine::startTransfer: could not start transfer"; + } +} + +/*! + DBus adaptor calls this method to restart a canceled or failed transfer with a \a transferId. In + a case of Upload, this method creates MediaItem instance of the existing transfer and instantiates + the required share plugin. The MediaItem instance is passed to the plugin and sharing is restarted. + + For Sync and Download entries, this method calls their callbacks methods, if a callback interface + has been defined by the client originally created the Sync or Download entry. +*/ +void TransferEngine::restartTransfer(int transferId) +{ + + Q_D(TransferEngine); + TransferEngineData::TransferType type = d->transferType(transferId); + if (type == TransferEngineData::Undefined) { + qWarning() << "TransferEngine::restartTransfer: failed to get transfer type"; + return; + } + + if (type == TransferEngineData::Upload) { + + MediaItem * item = DbManager::instance()->mediaItem(transferId); + if (!item) { + qWarning() << "TransferEngine::restartTransfer: failed to reload media item from db!"; + return; + } + + Q_D(TransferEngine); + MediaTransferInterface *muif = d->loadPlugin(item->value(MediaItem::PluginId).toString()); + muif->setMediaItem(item); + + connect(muif, SIGNAL(statusChanged(MediaTransferInterface::TransferStatus)), + d, SLOT(uploadItemStatusChanged(MediaTransferInterface::TransferStatus))); + connect(muif, SIGNAL(progressUpdated(qreal)), + d, SLOT(updateProgress(qreal))); + + d->m_keyTypeCache.insert(transferId, TransferEngineData::Upload); + d->m_plugins.insert(muif, transferId); + muif->start(); + return; + } + + TransferEngineData::TransferStatus status = DbManager::instance()->transferStatus(transferId); + // Check if this is canceled or interrupted transfer + // and make a callback call to the client. It's client's + // responsibility to update states properly + if (status == TransferEngineData::TransferCanceled || + status == TransferEngineData::TransferInterrupted) { + DbManager::instance()->updateProgress(transferId, 0); + d->callbackCall(transferId, TransferEnginePrivate::RestartCallback); + } +} + +/*! + Finishes an existing Sync or Download transfer with a \a transferId. Transfer can be finished + with different \a status e.g for successfully finish status can be set to + TransferEngineData::TransferFinished, for canceling TransferEngineData::Canceled and for + failure with TransferEngineData::TransferInterrupted. In a case of failure, the client can + also provide a \a reason. + + This method causes statusChanged() signal to be emitted. If a sync has been successfully + finished, then it will also be removed from the database automatically which causes + transferChanged() signal to be emitted. + */ +void TransferEngine::finishTransfer(int transferId, int status, const QString &reason) +{ + Q_UNUSED(reason); + Q_D(TransferEngine); + TransferEngineData::TransferType type = d->transferType(transferId); + if (type == TransferEngineData::Undefined || type == TransferEngineData::Upload) { + return; // We don't handle plugins here + } + + QUrl filePath; + // Read the file path from the database for download + if (type == TransferEngineData::Download) { + MediaItem *mediaItem = DbManager::instance()->mediaItem(transferId); + if (!mediaItem) { + qWarning() << "TransferEngine::finishTransfer: Failed to fetch MediaItem"; + return; + } + filePath = mediaItem->value(MediaItem::Url).toUrl(); + } + + + TransferEngineData::TransferStatus transferStatus = static_cast(status); + if (transferStatus == TransferEngineData::TransferFinished || + transferStatus == TransferEngineData::TransferCanceled || + transferStatus == TransferEngineData::TransferInterrupted) { + DbManager::instance()->updateTransferStatus(transferId, transferStatus); + + d->sendNotification(type, transferStatus, filePath); + emit statusChanged(transferId, status); + + // We don't want to leave successfully finished syncs to populate the database, just remove it. + if (type == TransferEngineData::Sync && + transferStatus == TransferEngineData::TransferFinished) { + if (DbManager::instance()->removeTransfer(transferId)) { + emit transfersChanged(); + } + } + } +} + +/*! + DBus adaptor calls this method to update transfer progress of the transfer with a \a transferId and + with a new \a progress. +*/ +void TransferEngine::updateTransferProgress(int transferId, double progress) +{ + Q_D(TransferEngine); + TransferEngineData::TransferType type = d->transferType(transferId); + + if (type == TransferEngineData::Undefined || type == TransferEngineData::Upload) { + return; + } + + + if (DbManager::instance()->updateProgress(transferId, progress)) { + emit progressChanged(transferId, progress); + } else { + qWarning() << "TransferEngine::updateTransferProgress: Failed to update progress for " << transferId; + } +} + +/*! + DBus adaptor calls this method to fetch a list of transfers. This method returns QList. + */ +QList TransferEngine::transfers() +{ + return DbManager::instance()->transfers(); +} + +/*! + DBus adaptor calls this method to fetch a list of transfer methods. This method returns QList. + + Transfer methods are basically a list of share plugins installed to the system. + */ +QList TransferEngine::transferMethods() +{ + Q_D(TransferEngine); + return d->enabledPlugins(); +} + +/*! + DBus adaptor calls this method to clear all the finished, canceled or interrupted transfers in the database. + */ +void TransferEngine::clearTransfers() +{ + if (DbManager::instance()->clearTransfers()) { + emit transfersChanged(); + } else { + qWarning() << "TransferEngine::clearTransfers: Failed to clear finished transfers!"; + } +} + +/*! + DBus adaptor calls this method to cancel an existing transfer with a \a transferId. + + If the transfer is Upload, then this method calls MediaTransferInterface instance's + cancel method. In a case of Sync or Download this method calls client's cancel callback + method, if the one exists. + + Calling this method causes statusChanged() signal to be emitted. + */ +void TransferEngine::cancelTransfer(int transferId) +{ + + Q_D(TransferEngine); + TransferEngineData::TransferType type = d->transferType(transferId); + + // Handle canceling of Download or Sync + if (type == TransferEngineData::Download || type == TransferEngineData::Sync) { + d->callbackCall(transferId, TransferEnginePrivate::CancelCallback); + return; + } + + // Let plugin handle canceling of up upload + if (type == TransferEngineData::Upload) { + MediaTransferInterface *muif = d->m_plugins.key(transferId); + if (muif == 0) { + qWarning() << "TransferEngine::cancelTransfer: Failed to get MediaTransferInterface!"; + return; + } + + muif->cancel(); + } +} +/*! + DBus adaptor calls this method to enable or disable transfer speicific notifications + based on \a enable argument. +*/ +void TransferEngine::enableNotifications(bool enable) +{ + Q_D(TransferEngine); + if (d->m_notificationsEnabled != enable) { + d->m_notificationsEnabled = enable; + } +} + +/*! + DBus adaptor calls this method. + Returns true or false depending if notifications are enabled or disabled. +*/ +bool TransferEngine::notificationsEnabled() +{ + Q_D(TransferEngine); + return d->m_notificationsEnabled; +} + + + + + + diff --git a/src/transferengine.h b/src/transferengine.h new file mode 100644 index 0000000..0659555 --- /dev/null +++ b/src/transferengine.h @@ -0,0 +1,112 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef TRANSFERENGINE_H +#define TRANSFERENGINE_H + +#include +#include +#include + +#include "mediatransferinterface.h" +#include "transferdbrecord.h" +#include "transfermethodinfo.h" + +class MediaTransferInterface; +class TransferEnginePrivate; +class TransferEngine : public QObject +{ + Q_OBJECT +public: + + explicit TransferEngine(QObject *parent = 0); + ~TransferEngine(); + +public Q_SLOTS: + int uploadMediaItem( const QString &source, + const QString &serviceId, + const QString &mimeType, + bool metadataStripped, + const QVariantMap &userData); + + int uploadMediaItemContent(const QVariantMap &content, + const QString &serviceId, + const QVariantMap &userData); + + int createDownload(const QString &displayName, + const QString &applicationIcon, + const QString &serviceIcon, + const QString &filePath, + const QString &mimeType, + qlonglong expectedFileSize, + const QStringList &callback, + const QString &cancelMethod, + const QString &restartMethod); + + int createSync(const QString &displayName, + const QString &applicationIcon, + const QString &serviceIcon, + const QStringList &callback, + const QString &cancelMethod, + const QString &restartMethod); + + void startTransfer(int transferId); + + void restartTransfer(int transferId); + + void finishTransfer(int transferId, int status, const QString &reason); + + void updateTransferProgress(int transferId, double progress); + + QList transfers(); + + QList transferMethods(); + + void clearTransfers(); + + void cancelTransfer(int transferId); + + void enableNotifications(bool enable); + + bool notificationsEnabled(); + +Q_SIGNALS: + void progressChanged(int transferId, double progress); + + void statusChanged(int transferId, int status); + + void transferMethodListChanged(); + + void transfersChanged(); + + +private: + TransferEnginePrivate *d_ptr; + Q_DECLARE_PRIVATE(TransferEngine) +}; + + +#endif // TRANSFERENGINE_H diff --git a/src/transferengine_p.h b/src/transferengine_p.h new file mode 100644 index 0000000..8aaa23a --- /dev/null +++ b/src/transferengine_p.h @@ -0,0 +1,123 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef TRANSFERENGINE_P_H +#define TRANSFERENGINE_P_H + +#include +#include +#include +#include + +#include "mediatransferinterface.h" +#include "transfermethodinfo.h" + +#include + +class QFileSystemWatcher; +class QTimer; +class QUrl; +class TransferEngine; +class TransferPluginInfo; + +class TransferEngineSignalHandler: public QObject +{ + Q_OBJECT +public: + static TransferEngineSignalHandler * instance(); + static void signalHandler(int signal); + +Q_SIGNALS: + void exitSafely(); + +private: + TransferEngineSignalHandler(); +}; + + +class TransferEnginePrivate: QObject +{ + Q_OBJECT +public: + // CallbackElement enum is used as an accessor to DBus callback + // information from a list. Enums are used as an indeces. + enum CallbackElements { + Service = 0, + Path, + Interface + }; + + // CallbackMethodType enum is used as an accessor to the list where + // method names starts from the index 3. + enum CallbackMethodType { + CancelCallback = 3, + RestartCallback = 4 + }; + + TransferEnginePrivate(TransferEngine *parent); + void recoveryCheck(); + void sendNotification(TransferEngineData::TransferType type, + TransferEngineData::TransferStatus status, + const QUrl &filePath); + int uploadMediaItem(MediaItem *mediaItem, + MediaTransferInterface *muif, + const QVariantMap &userData); + inline TransferEngineData::TransferType transferType(int transferId); + void callbackCall(int transferId, CallbackMethodType method); + MRemoteAction createRemoteActionForGroup(); + +public Q_SLOTS: + void exitSafely(); + void inProgressTransfersCheck(); + void enabledPluginsCheck(); + void pluginDirChanged(); + void uploadItemStatusChanged(MediaTransferInterface::TransferStatus status); + void updateProgress(qreal progress); + void pluginInfoReady(); + void pluginInfoError(const QString &msg); + +public: + QStringList pluginList() const; + QList enabledPlugins() const; + MediaTransferInterface *loadPlugin(const QString &pluginId) const; + + + QMap m_plugins; + QMap m_keyTypeCache; + bool m_notificationsEnabled; + QList m_infoObjects; + QList m_enabledPlugins; + Accounts::Manager *m_accountManager; + QFileSystemWatcher *m_fileWatcher; + QTimer *m_fileWatcherTimer; + QSettings m_settings; + quint32 m_transfersInProgressCount; + TransferEngine *q_ptr; + Q_DECLARE_PUBLIC(TransferEngine) +}; + +#endif + diff --git a/tests/main.cpp b/tests/main.cpp new file mode 100644 index 0000000..40f113e --- /dev/null +++ b/tests/main.cpp @@ -0,0 +1,41 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include +#include "ut_imageoperation.h" +#include "ut_mediatransferinterface.h" + +int main(int argc, char *argv[]) +{ + + ut_imageoperation t1; + int res = QTest::qExec(&t1); + + ut_mediatransferinterface t2; + res = QTest::qExec(&t2); + + return res; +} diff --git a/tests/testimage.jpg b/tests/testimage.jpg new file mode 100644 index 0000000..47bbb0f Binary files /dev/null and b/tests/testimage.jpg differ diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 index 0000000..cff131b --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,37 @@ +TEMPLATE = app +DEPENDPATH += . +INCLUDEPATH += . ../src ../lib + + +# Test files +HEADERS += \ + ut_imageoperation.h \ + ut_mediatransferinterface.h + +SOURCES += \ + main.cpp \ + ut_imageoperation.cpp \ + ut_mediatransferinterface.cpp + + +# Import filess from the actual project +HEADERS += \ + ../lib/imageoperation.h \ + ../lib/mediatransferinterface.h \ + ../lib/mediaitem.h + +SOURCES += \ + ../lib/imageoperation.cpp \ + ../lib/mediatransferinterface.cpp \ + ../lib/mediaitem.cpp + + +LIBS += -lquillmetadata +QT += testlib + +PATH = /opt/tests/nemo-transfer-engine +resources.files = testimage.jpg +resources.path = $$PATH +target.path = $$PATH + +INSTALLS += target resources diff --git a/tests/ut_imageoperation.cpp b/tests/ut_imageoperation.cpp new file mode 100644 index 0000000..c2120f0 --- /dev/null +++ b/tests/ut_imageoperation.cpp @@ -0,0 +1,190 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include "ut_imageoperation.h" +#include +#include +#include "imageoperation.h" +#include +#include + +QString ut_imageoperation::createTestFile(const QString &fileName, bool writeContent) +{ + QString f = QDir::tempPath() + QDir::separator() + fileName; + if (writeContent) { + QFile file(f); + file.open(QIODevice::WriteOnly); + const char * msg = "content"; + file.write(msg, qstrlen(msg)); + file.close(); + } + return f; +} + +void ut_imageoperation::testUniqueFilePath() +{ + QStringList tempFiles; + tempFiles << createTestFile("img_001.jpg"); + + // Bad input + QCOMPARE(ImageOperation::uniqueFilePath(QString()), QString()); + + // Non existing file + QCOMPARE(ImageOperation::uniqueFilePath(QLatin1String("/home/nemo/Pictures/img_001.jpg")), QString()); + + // Existing file + QStringList tmp; + tmp << ImageOperation::uniqueFilePath(tempFiles.at(0)); + QCOMPARE(tmp.last().endsWith(QLatin1String("_1.jpg")), true); + tmp.clear(); + + // Add two more files + tempFiles << createTestFile("img_002.jpg") + << createTestFile("img_004.jpg"); + + // Create couple of temp files from the same source file. Note files must exists + // on a disk + tmp << ImageOperation::uniqueFilePath(tempFiles.at(2)); + QFile::copy(tempFiles.at(2), tmp.last()); + QCOMPARE(tmp.last().endsWith(QLatin1String("_1.jpg")), true); + + tmp << ImageOperation::uniqueFilePath(tempFiles.at(2)); + QFile::copy(tempFiles.at(2), tmp.last()); + QCOMPARE(tmp.last().endsWith(QLatin1String("_2.jpg")), true); + + // Remove the first file. This should handle the case that we are not getting + // a new temp file with _2.jpg as a suffix because this should take into account + // the removed files too. + QFile::remove(tmp.first()); + QCOMPARE(ImageOperation::uniqueFilePath(tempFiles.at(2)).endsWith("_3.jpg"), true); + + // Remove all the files generated for this test case + foreach(QString f, tmp) { + QFile::remove(f); + } + + foreach(QString f, tempFiles) { + QFile::remove(f); + } +} + + +void ut_imageoperation::testScale() +{ + + QImage img("testimage.jpg"); + QVERIFY(!img.isNull()); + + QString filePath("testimage.jpg"); + + QString target = ImageOperation::uniqueFilePath(filePath); + + // Invalid sourceFile -> fail + QCOMPARE(ImageOperation::scaleImage("", 0.5, target), QString()); + + // Valid source file, invalid scaleFactor -> fail + QCOMPARE(ImageOperation::scaleImage(filePath, -1.0, target), QString()); + QCOMPARE(ImageOperation::scaleImage(filePath, 0, target), QString()); + QCOMPARE(ImageOperation::scaleImage(filePath, 1.0, target), QString()); + + // Proper source file, proper scale factor, proper target file + QString result = ImageOperation::scaleImage(filePath, 0.5, target); + QCOMPARE(result, target); + + QImage resImage(result); + QCOMPARE(resImage.size(), img.size()*0.5); + QFile::remove(result); + + result = ImageOperation::scaleImage(filePath, 0.1, target); + resImage.load(result); + QCOMPARE(resImage.size(), img.size()*0.1); + QFile::remove(result); + + result = ImageOperation::scaleImage(filePath, 0.9, target); + resImage.load(result); + QVERIFY(qAbs(resImage.width() - img.width()*0.9) < 2); + QVERIFY(qAbs(resImage.height() - img.height()*0.9) < 2); + QFile::remove(result); +} + +void ut_imageoperation::testDropMetadata() +{ + // NOTE: The test image doesn't contain all metadata fields such as + // title description, but it contains the most essential fields related + // to location and the author. + // First make sure that there is metadata + QCOMPARE(QuillMetadata::canRead("testimage.jpg"), true); + QuillMetadata md("testimage.jpg"); + QCOMPARE(md.isValid(), true); + + QVariant creator = md.entry(QuillMetadata::Tag_Creator); + QVariant city = md.entry(QuillMetadata::Tag_City); + QVariant country = md.entry(QuillMetadata::Tag_Country); + QVariant location= md.entry(QuillMetadata::Tag_Location); + QVariant lat = md.entry(QuillMetadata::Tag_GPSLatitude); + QVariant lon = md.entry(QuillMetadata::Tag_GPSLongitude); + + // These shound't be null for the original image + QCOMPARE(creator.isNull(), false); + QCOMPARE(city.isNull(), false); + QCOMPARE(country.isNull(), false); + QCOMPARE(location.isNull(),false); + QCOMPARE(lat.isNull(), false); + QCOMPARE(lon.isNull(), false); + + QString path = ImageOperation::removeImageMetadata("testimage.jpg"); + QVERIFY(!path.isNull()); + QCOMPARE(QFile::exists(path), true); + + + QCOMPARE(QuillMetadata::canRead(path), true); + QuillMetadata md2(path); + QCOMPARE(md2.isValid(), true); + + creator = md2.entry(QuillMetadata::Tag_Creator); + city = md2.entry(QuillMetadata::Tag_City); + country = md2.entry(QuillMetadata::Tag_Country); + location= md2.entry(QuillMetadata::Tag_Location); + lat = md2.entry(QuillMetadata::Tag_GPSLatitude); + lon = md2.entry(QuillMetadata::Tag_GPSLongitude); + + // After removing metadata these should be fine. + QCOMPARE(creator.isNull(), true); + QCOMPARE(city.isNull(), true); + QCOMPARE(country.isNull(), true); + QCOMPARE(location.isNull(),true); + QCOMPARE(lat.isNull(), true); + QCOMPARE(lon.isNull(), true); + + // Remove the test image + QFile::remove(path); +} + +/* +QTEST_MAIN(ut_imageoperation) + +#include "ut_imageoperation.moc" +*/ diff --git a/tests/ut_imageoperation.h b/tests/ut_imageoperation.h new file mode 100644 index 0000000..f07e5f8 --- /dev/null +++ b/tests/ut_imageoperation.h @@ -0,0 +1,45 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef UT_IMAGEOPERATION_H +#define UT_IMAGEOPERATION_H + +#include + +class ut_imageoperation : public QObject +{ + Q_OBJECT +public: + + QString createTestFile(const QString &fileName, bool writeContent = true); + +private slots: + void testScale(); + void testDropMetadata(); + void testUniqueFilePath(); +}; + +#endif // UT_IMAGEOPERATION_H diff --git a/tests/ut_mediatransferinterface.cpp b/tests/ut_mediatransferinterface.cpp new file mode 100644 index 0000000..59ad0b7 --- /dev/null +++ b/tests/ut_mediatransferinterface.cpp @@ -0,0 +1,178 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#include "ut_mediatransferinterface.h" +#include "mediaitem.h" +#include +#include +#include +#include + + +QString TestInterface::displayName() const +{ + return "Test"; +} + +QUrl TestInterface::serviceIcon() const +{ + return QUrl(); +} + +bool TestInterface::cancelEnabled() const +{ + return true; +} + +bool TestInterface::restartEnabled() const +{ + return true; +} + +void TestInterface::start() +{ + +} + +void TestInterface::cancel() +{ + +} + +// ************************ + + + + +void ut_mediatransferinterface::init() +{ + tf = new TestInterface(); + qRegisterMetaType("MediaTransferInterface::TransferStatus"); +} + +void ut_mediatransferinterface::cleanup() +{ + delete tf; + tf = 0; +} + + +void ut_mediatransferinterface::testSetMediaItem() +{ + QVERIFY(tf != 0); + + MediaItem *mi = new MediaItem; + QVariantMap map; + map.insert("key1", 1); + map.insert("key2", 2); + mi->setValue(MediaItem::UserData, map); + + tf->setMediaItem(mi); + QCOMPARE(tf->mediaItem(), mi); + QCOMPARE(tf->mediaItem()->parent(), tf); + + QVariantMap map2 = tf->mediaItem()->value(MediaItem::UserData).toMap(); + QCOMPARE(map2.value("key1"), map.value("key1")); + QCOMPARE(map2.value("key2"), map.value("key2")); +} + +void ut_mediatransferinterface::testProgress() +{ + QVERIFY(tf != 0); + + QSignalSpy spy(tf, SIGNAL(progressUpdated(qreal))); + + QVERIFY(tf->progress() == 0); + QCOMPARE(spy.count(), 0); + + tf->setProgress(0.01); + QVERIFY(tf->progress() > 0); + // Test that first signal is only emitted after the threshold value (0.05) has + // been exceeded. + tf->setProgress(0.02); + tf->setProgress(0.03); + tf->setProgress(0.04); + tf->setProgress(0.05); + tf->setProgress(0.06); + QCOMPARE(spy.count(), 1); + + tf->setProgress(0.11); + QCOMPARE(spy.count(), 2); + + tf->setProgress(0.21); + QCOMPARE(spy.count(), 3); + + tf->setProgress(0.31); + QCOMPARE(spy.count(), 4); + + tf->setProgress(0.41); + QCOMPARE(spy.count(), 5); + + + // Let's set status to finished -> one progressUpdated signal should be emitted + tf->setStatus(MediaTransferInterface::TransferFinished); + QCOMPARE(spy.count(), 6); + QVERIFY(tf->progress() == 1); + + // Set progress to less than 1 + tf->setProgress(0.5); + QCOMPARE(spy.count(), 7); + + // Cancel the transfer. This is handled in the same if as handing Interrupted transfer + tf->setStatus(MediaTransferInterface::TransferCanceled); + QCOMPARE(spy.count(), 8); + QVERIFY(tf->progress() == 0); +} + + + +void ut_mediatransferinterface::testStatus_data() +{ + QTest::addColumn("status"); + QTest::addColumn("spycount"); + + QTest::newRow("notstarted") << MediaTransferInterface::NotStarted << 0; + QTest::newRow("starter") << MediaTransferInterface::TransferStarted << 1; + QTest::newRow("canceled") << MediaTransferInterface::TransferCanceled << 1; + QTest::newRow("interrupted") << MediaTransferInterface::TransferInterrupted << 1; + QTest::newRow("finished") << MediaTransferInterface::TransferFinished << 1; +} + +void ut_mediatransferinterface::testStatus() +{ + + QVERIFY(tf != 0); + QFETCH(MediaTransferInterface::TransferStatus, status); + QFETCH(int, spycount); + + QSignalSpy spy(tf, SIGNAL(statusChanged(MediaTransferInterface::TransferStatus))); + tf->setStatus(status); + QCOMPARE(tf->status(), status); + QCOMPARE(spy.count(), spycount); +} + + +Q_DECLARE_METATYPE(MediaTransferInterface::TransferStatus) diff --git a/tests/ut_mediatransferinterface.h b/tests/ut_mediatransferinterface.h new file mode 100644 index 0000000..6c0ccce --- /dev/null +++ b/tests/ut_mediatransferinterface.h @@ -0,0 +1,69 @@ +/**************************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Marko Mattila +** All rights reserved. +** +** This file is part of Nemo Transfer Engine package. +** +** You may use this file under the terms of the GNU Lesser General +** Public License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file license.lgpl included in the packaging +** of this file. +** +** This library 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 +** Lesser General Public License for more details. +** +****************************************************************************************/ + +#ifndef UT_MEDIATRANSFERINTERFACE_H +#define UT_MEDIATRANSFERINTERFACE_H + +#include +#include "mediatransferinterface.h" +class TestInterface: public MediaTransferInterface +{ + Q_OBJECT +public: + + QString displayName() const; + QUrl serviceIcon() const; + bool cancelEnabled() const; + bool restartEnabled() const; + +public slots: + void start(); + void cancel(); + +public: + friend class ut_mediatransferinterface; +}; + + +// Ut class +class ut_mediatransferinterface: public QObject +{ + Q_OBJECT +public: + +private slots: + void init(); + void cleanup(); + void testSetMediaItem(); + void testProgress(); + void testStatus_data(); + void testStatus(); + +private: + TestInterface *tf; +}; + +#endif // UT_MEDIATRANSFERINTERFACE_H diff --git a/transfer-engine.pro b/transfer-engine.pro new file mode 100644 index 0000000..1c7870f --- /dev/null +++ b/transfer-engine.pro @@ -0,0 +1,17 @@ +TEMPLATE = subdirs +SUBDIRS = lib src tests +CONFIG += ordered + +include(doc/doc.pri) + +OTHER_FILES += \ + rpm/transfer-engine.spec \ + nemo-transfer-engine.conf \ + doc/src/* \ + doc/config/* + + +config.files = nemo-transfer-engine.conf +config.path = /home/nemo/.config/nemomobile + +INSTALLS += config diff --git a/translations/translations.pro b/translations/translations.pro new file mode 100644 index 0000000..ce35bc2 --- /dev/null +++ b/translations/translations.pro @@ -0,0 +1,30 @@ +TEMPLATE = aux + +TS_FILE = $$OUT_PWD/nemo-transfer-engine.ts +EE_QM = $$OUT_PWD/nemo-transfer-engine_eng_en.qm + +ts.commands += lupdate $$PWD/.. -ts $$TS_FILE +ts.CONFIG += no_check_exist no_link +ts.output = $$TS_FILE +ts.input = .. + +ts_install.files = $$TS_FILE +ts_install.path = /usr/share/translations/source +ts_install.CONFIG += no_check_exist + +# should add -markuntranslated "-" when proper translations are in place (or for testing) +engineering_english.commands += lrelease -idbased $$TS_FILE -qm $$EE_QM +engineering_english.CONFIG += no_check_exist no_link +engineering_english.depends = ts +engineering_english.input = $$TS_FILE +engineering_english.output = $$EE_QM + +engineering_english_install.path = /usr/share/translations +engineering_english_install.files = $$EE_QM +engineering_english_install.CONFIG += no_check_exist + +QMAKE_EXTRA_TARGETS += ts engineering_english + +PRE_TARGETDEPS += ts engineering_english + +INSTALLS += ts_install engineering_english_install