ãã®èšäºã§ã¯ãMeego Harmattanã®äŸã§QtComponentsã䜿çšããŠãœãããŠã§ã¢ãéçºããçµéšãHabrasocietyãšå ±æããããšæããŸãã Ubuntu Oneã䜿çšããŠåæããããŒããšãã£ã¿ãŒãäœæããŸãã
ãã¹ãŠã®éçºã¯ã¹ã¯ã©ããããã¯ã¹ã䜿çšããŠå®è¡ãããmaddeãšæ¯èŒããŠããã€ãã®å©ç¹ããããŸãããLinuxã·ã¹ãã ã§ã®ã¿æ©èœããŸãã
äž»ãªå©ç¹ã®äžã§ãã¢ã»ã³ããªã¯chrootã§å®è¡ãããã¢ãŒã¡ã«ã®å Žåã¯ãšãã¥ã¬ãŒã·ã§ã³ã«qemuã䜿çšãããããšã«æ³šæããŠãã ããã æ¡ä»¶ã¯å¯èœãªéãæŠéã«è¿ãã§ãã ããã«ãããã¯ãã¹ã³ã³ãã€ã«ãèšå®ããäœåãªæéãçããŸãã ããã«ãã©ã¹ã¯ãapt-getã®ååšã§ããããã¯ãã¢ã»ã³ããªã«å¿ èŠãªãã¹ãŠã®äŸåé¢ä¿ãã€ã³ã¹ããŒã«ã§ããŸããããã¯ãhelloworldãããé£ããã¢ããªã±ãŒã·ã§ã³ãäœæãããšãã«ééããªãå¿ èŠã«ãªããŸãã
ã¹ã¯ã©ããããã¯ã¹ãã€ã³ã¹ããŒã«ããŠæ§æãã
scratchboxãã€ã³ã¹ããŒã«ããã«ã¯ããã®ã¹ã¯ãªãããã«ãŒãããããŠã³ããŒãããŠå®è¡ããå°æ¥ãã®æ瀺ã«åŸãå¿ èŠããããŸãã
# ./harmattan-sdk-setup.py
ã€ã³ã¹ããŒã«åŸããŠãŒã¶ãŒãsboxã°ã«ãŒãã«æ£åžžã«è¿œå ãããããã«ãã°ã€ã³ããå¿ èŠããããŸãã
次ã®ã³ãã³ãã䜿çšããŠã¹ã¯ã©ããããã¯ã¹ãèµ·åããŸãã
$ /scratchbox/login
ã€ã³ã¹ããŒã©ãŒãæ£åžžã«æ©èœããå Žåã次ã®ãããªããã³ããã衚瀺ãããŸãã
[sbox-HARMATTAN_ARMEL: ~] >
ãã°ã€ã³ãèªãå Žåã¯ãscratchboxã®ã«ãŒãã«ããrun_me_first.shã¹ã¯ãªãããå®è¡ããŠã¿ãŠãã ããã sb_menuã䜿çšããŠãç®çã®ã¿ãŒã²ãããéžæã§ããŸãã æ®ãã®ã¹ã¯ã©ããããã¯ã¹ã®äœ¿çšã¬ã€ãã¯ãã¡ãã«ãããŸãã
cmakeãããžã§ã¯ãã®äœæ
ã³ã¬ã¯ã¿ãŒãšããŠãç§ã¯éåžžã®qmakeã䜿çšããŸããããäŸåé¢ä¿ãæ¢ãããšãã§ãããã匷åãªcmakeã䜿çšããå€æ°ã®æ§æãªãã·ã§ã³ãåããŠãããã¯ãã¹ãã©ãããã©ãŒã éçºã«ããé©ããŠããŸãã ãã®èšäºã§ã¯ãã¢ã»ã³ããªã·ã¹ãã ã®åæã«ã€ããŠã¯è©³ãã説æããŸããã®ã§ãç解ãæ·±ããããã«ããã®èšäºãèªãããšããå§ãããŸã ã
å¯äžã®ãã€ãã¹ç¹ã¯ãcmakeãSymbianã®äœ¿çšæ¹æ³ãç¥ããªãããšã§ãããã®ãããä»ã®ãšããããã®ãã©ãããã©ãŒã ãå¿ãããããã®ãã©ãããã©ãŒã å°çšã®ã¢ã»ã³ããªçšã«ç¹å¥ãªãããžã§ã¯ããæåã§èšè¿°ã§ããŸãã Cmakeã¯æ®ãã®éšåãç°¡åã«åŠçã§ããã®ã§ãå°æ¥ã¯ãã®ã¢ããªã±ãŒã·ã§ã³ããã¹ã¯ãããã·ã¹ãã ã«ãå Žåã«ãã£ãŠã¯Androidã«ãããã«ã¯iOSã«ç§»æ€ããäºå®ã§ãã
ãã®ãããžã§ã¯ãã¯ãgitãµãã¢ãžã¥ãŒã«ã䜿çšããŠã¡ã€ã³ãªããžããªã«æ¥ç¶ãããŠããå€æ°ã®äŸåã©ã€ãã©ãªã§æ§æãããŠããŸããåã©ã€ãã©ãªã«ã¯ãç¬èªã®cmakeãããžã§ã¯ãããããŸãã ãããã¯ãã¹ãŠãµãŒãããŒãã£ã®ãã£ã¬ã¯ããªã«ãããã¡ã€ã³ãããžã§ã¯ãã«æ¥ç¶ãããŠãããããharmattanãªããžããªã«ãªãäž»èŠãªäŸåé¢ä¿ãããã«ã¢ã»ã³ããªã«åæ ãããŸãã
ãµãŒãããŒãã£ã©ã€ãã©ãªã®ãªã¹ãïŒ
- QOauth-Qtã§ã®Oauthãããã³ã«ã®å®è£
- k8jsonã¯éåžžã«é«éãªJSONããŒãµãŒã§ã
- QmlObjectModel-ã¢ãã«ãå®è£ ããã¯ã©ã¹-ãªããžã§ã¯ãã®ãªã¹ã
ããã«å ããŠãã¢ã»ã³ããªã«å¿ èŠãªå€éšã©ã€ãã©ãªããããŸãããã¡ã€ã³ã®Harmattanã®ã«ãã«ååšããqcaã¯ããããåç §ããããã«ã€ã³ã¹ããŒã«ããcmakeãã€ã³ã¹ããŒã«ããŸãïŒ
[sbox-HARMATTAN_ARMEL: ~] > apt-get install libqca2-dev cmake
ããã䜿çšã§ããããã«ããã«ã¯ãã©ã€ãã©ãªããããŒãã¡ã€ã«ãšã©ã€ãã©ãªãã¡ã€ã«èªäœãå«ããã£ã¬ã¯ããªãèŠã€ããŠãªã³ã¯ã§ããç¹å¥ãªcmakeãã¡ã€ã«ãäœæããå¿ èŠããããŸãã
include(FindLibraryWithDebug) if(QCA2_INCLUDE_DIR AND QCA2_LIBRARIES) # in cache already set(QCA2_FOUND TRUE) else(QCA2_INCLUDE_DIR AND QCA2_LIBRARIES) if(NOT WIN32) find_package(PkgConfig) pkg_check_modules(PC_QCA2 QUIET qca2) set(QCA2_DEFINITIONS ${PC_QCA2_CFLAGS_OTHER}) endif(NOT WIN32) find_library_with_debug(QCA2_LIBRARIES WIN32_DEBUG_POSTFIX d NAMES qca HINTS ${PC_QCA2_LIBDIR} ${PC_QCA2_LIBRARY_DIRS} ${QT_LIBRARY_DIR}) find_path(QCA2_INCLUDE_DIR QtCrypto HINTS ${PC_QCA2_INCLUDEDIR} ${PC_QCA2_INCLUDE_DIRS} ${QT_INCLUDE_DIR}} PATH_SUFFIXES QtCrypto) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(QCA2 DEFAULT_MSG QCA2_LIBRARIES QCA2_INCLUDE_DIR) mark_as_advanced(QCA2_INCLUDE_DIR QCA2_LIBRARIES) endif(QCA2_INCLUDE_DIR AND QCA2_LIBRARIES)
ã»ãšãã©ã®äŸåé¢ä¿ã®æ€çŽ¢ã¯ãåãã¹ã¿ã€ã«ã§èšè¿°ãããŠããŸãã Harmattanãå«ãpgkconfigãåããã·ã¹ãã ã§ã¯ããã¹ãŠãã·ã³ãã«ã§æ確ã§ããããã§ãªãã·ã¹ãã ã§ã¯ã$ QTDIRãã£ã¬ã¯ããªã調ã¹ãŸãã cmakeãã©ã€ãã©ãªãèªåçã«æ€åºããªãã£ãå Žåãå€æ°QCA2_INCLUDE_DIR QCA2_LIBRARIESãæåã§èšå®ããããšãææ¡ããŸãã ãã®ã¢ãããŒãã«ãããããã±ãŒãžãããŒãžã£ãŒã®ãªãã·ã¹ãã ã§ã®äœæ¥ã楜ã«ãªããŸãã
cmakeã«ã¯ããã®ããã°ã©ã ãŸãã¯ãã®ããã°ã©ã ããã«ããããŠãããã©ââãããã©ãŒã ãå€å¥ã§ããå€æ°ããããŸããäŸãã°ïŒ
if(WIN32) .... elseif(APPLE) ... elseif(LINUX) ... endif()
æ®å¿µãªãããcmakeã¯Harmattanã«ã€ããŠäœãç¥ããŸãããæãç°¡åãªè§£æ±ºçã¯ã-DHARMATTAN = ONã¹ã€ããã§cmakeãéå§ããããšã§ãã ããã§HARMATTANå€æ°ãå®çŸ©ããã次ã®ããã«èšè¿°ã§ããŸãã
if(HARMATTAN) add_definitions(-DMEEGO_EDITION_HARMATTAN) # , . endif()
ãããã®åãå€æ°ã䜿çšããŠãã€ã³ã¹ããŒã«ããGUIå®è£ ã決å®ã§ããŸãã
if(HARMATTAN) set(CLIENT_TYPE meego) message(STATUS "Using meego harmattan client") else() set(CLIENT_TYPE desktop) list(APPEND QML_MODULES QtDesktop) message(STATUS "Using desktop client") endif() set(QML_DIR "${CMAKE_CURRENT_SOURCE_DIR}/qml/${CLIENT_TYPE}") ... install(DIRECTORY ${QML_DIR} DESTINATION ${SHAREDIR}/qml)
éçºã§ã¯ãã»ãšãã©ã®å Žåãharmattanã¯ã€ãã¯ã³ã³ããŒãã³ããšã¢ã»ã³ããªäžã®-DHARMATTANã¹ã€ãããåããQtSDKã§ååã§ãã scratchboxã§ã¯ãæçµããŒãžã§ã³ãå€å°åéããã®ãçã«ããªã£ãŠããŸãã
Tomboy Notes APIãå®è£ ããC ++ãã©ã°ã€ã³
APIèªäœãå¥ã®qmlã¢ãžã¥ãŒã«ã«åã蟌ãããšã«ããŸããããã®ã¢ãžã¥ãŒã«ã¯importãã£ã¬ã¯ãã£ããä»ããŠå©çšã§ããŸãã ããã¯ãGUIã€ã³ã¿ãŒãã§ãŒã¹ã®ããŸããŸãªå®è£ ãäœæããããã«äŸ¿å©ã§ãã
éçºããã»ã¹ã§æãå°é£ãªéšåã¯ãOAuthã䜿çšããŠæ¿èªãå®è£ ããããšã§ããããã®éã«ãããã€ãã®ç°ãªãã©ã€ãã©ãªã®å®è£ ãåæãããçŸæç¹ã§ã¯QOauthã«èœã¡çããŸããã ãã®ã©ã€ãã©ãªã®èª¬æãèšèŒãããHabréã®èšäºãããã®ã§ãããã«å·®ãè¿«ã£ãåé¡ã®è§£æ±ºã«é²ã¿ãŸãã ãŸãæåã«ãéåžžã«åæãããŠããããŒã¯ã³ãååŸããå¿ èŠããããŸãã
ããã¯ããªãããŒãªããžãã¹ã§ã¯ãããŸãããã¢ãã¬ã¹ã«ãªã¯ãšã¹ããéä¿¡ããhttpsãä»ããåºæ¬èªèšŒã®ãªã¯ãšã¹ããå±ãã®ãåŸ ã¡ãŸãã
UbuntuOneApi::UbuntuOneApi(QObject *parent) : QObject(parent), m_manager(new QNetworkAccessManager(this)), m_oauth(new QOAuth::Interface(this)) { ... connect(m_manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), SLOT(onAuthenticationRequired(QNetworkReply*,QAuthenticator*))); } ... void UbuntuOneApi::requestToken(const QString &email, const QString &password) { m_email = email; m_password = password; QUrl url("https://login.ubuntu.com/api/1.0/authentications"); url.addQueryItem(QLatin1String("ws.op"), QLatin1String("authenticate")); url.addQueryItem(QLatin1String("token_name"), QLatin1Literal("Ubuntu One @ ") % m_machineName); qDebug() << url.toEncoded(); QNetworkRequest request(url); QNetworkReply *reply = m_manager->get(request); reply->setProperty("email", email); reply->setProperty("password", password); connect(reply, SIGNAL(finished()), SLOT(onAuthReplyFinished())); } ... void UbuntuOneApi::onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *auth) { auth->setUser(reply->property("email").toString()); auth->setPassword(reply->property("password").toString()); }
ãæ°ã¥ããããããŸããããQNetworkAccessManagerã®æšæºã§ããauthenticationRequiredä¿¡å·ã¯èªèšŒã«äœ¿çšãããŸããéåžžã®éå ·ã§ãã°ã€ã³ãšãã¹ã¯ãŒããèŠããŠããã ãã§ãã 䟿å©ã§ãäžå¿ èŠãªè©³çŽ°ã§ã€ã³ã¿ãŒãã§ãŒã¹ãè©°ãŸãããŸããã
å®äºãããšãå¿çã¯ç®çã®ããŒã¯ã³ãšãã®ä»ã®éèŠãªæ å ±ãå«ãjson圢åŒã§è¿ä¿¡ãããŸãã ããã¯ãk8jsonã©ã€ãã©ãªãå¿ èŠãªå Žæã§ãã
QNetworkReply *reply = static_cast<QNetworkReply*>(sender()); QVariantMap response = Json::parse(reply->readAll()).toMap(); if (response.isEmpty()) { emit authorizationFailed(tr("Unable to recieve token")); } m_token = response.value("token").toByteArray(); m_tokenSecret = response.value("token_secret").toByteArray(); m_oauth->setConsumerKey(response.value("consumer_key").toByteArray()); m_oauth->setConsumerSecret(response.value("consumer_secret").toByteArray()); QUrl url("https://one.ubuntu.com/oauth/sso-finished-so-get-tokens/" + reply->property("email").toString()); connect(get(url), SIGNAL(finished()), SLOT(onConfirmReplyFinished()));
次ã®ã¹ãããã¯ãããŒã¯ã³ãåãåã£ããšããäºå®ã®ç¢ºèªãéä¿¡ããããšã§ãïŒæåŸã®è¡ã«æ³šæãæã£ãŠãã ããïŒã ãã®çµæãçãã¯å€§äžå€«ã§ãã
void UbuntuOneApi::onConfirmReplyFinished() { QNetworkReply *reply = static_cast<QNetworkReply*>(sender()); QByteArray data = reply->readAll(); if (data.contains("ok")) { emit hasTokenChanged();
ãã®ãããªåèªãçãã«å«ãŸããŠããå Žåããã¹ãŠãããªãã¯åãã§ãžã£ã³ãããããŒã¯ã³ãæçµçã«åä¿¡ãããããšã瀺ãä¿¡å·ãéä¿¡ããã¡ã¢ã§äœæ¥ãéå§ã§ããŸãããããã«ã¯ãããŸããã§ããïŒ tomboy apiãšã®äºææ§ã®ããã«ãããŒããµãŒããŒã¯Webãã©ãŠã¶ãŒãä»ããèªèšŒãå¿ èŠãšããŸãã ãããŸã§ã®ãšããããã®åé¡ãåé¿ããããšãã§ãããæ¯ã磚ãããã«ãããã®ãŠãŒã¶ãŒãã¡ã¢ã«ã¢ã¯ã»ã¹ã§ããããã«ããããã¿ã³ãå«ããŠã£ã³ããŠãWebkitã¢ããªã±ãŒã·ã§ã³ã«è¿œå ããå¿ èŠããããŸããã ãã®Webkitã«QNetworkAccessManagerãžã®ãã€ã³ã¿ãäžããèªèšŒãæ£åžžã«å®äºãããšãèªèšŒã«å¿ èŠãªããŒã¿ãå«ã倧åãªCookieã®ææè ã«ãªããŸãã
ãŸãããŠãŒã¶ãŒããŠãŒã¶ãŒåãšãã¹ã¯ãŒããååºŠå ¥åããå¿ èŠããªãããã«ããããã®ãã£ãŒã«ãã«DOMããªãŒãå ¥åããŸãã
QWebFrame *frame = page()->mainFrame(); QWebElement email = frame->findFirstElement("#id_email"); email.setAttribute("value", m_email); QWebElement pass = frame->findFirstElement("#id_password"); pass.setAttribute("value", m_password); QWebElement submit = frame->findFirstElement("#continue"); submit.setFocus();
åãåã£ãCookieãä¿åããããšãå¿ããªãã§ãã ããã
void Notes::onWebAuthFinished(bool success) { if (success) { QNetworkCookieJar *jar = m_api->manager()->cookieJar(); QList<QNetworkCookie> cookies = jar->cookiesForUrl(m_apiRef); QSettings settings; settings.beginWriteArray("cookies", cookies.count()); for (int i = 0; i != cookies.count(); i++) { settings.setArrayIndex(i); settings.setValue("cookie", cookies.at(i).toRawForm()); } settings.endArray(); sync(); } }
ãµãŒããŒããªã¯ãšã¹ããæ£åžžã«åŠçããã«ã¯ãããããŒã«ä»¥åã«åãåã£ãããŒã¯ã³ãå«ãŸããŠããå¿ èŠããããŸãã ããã¯ãQOauthã䟿å©ãªå Žæã§ãã
QNetworkReply *UbuntuOneApi::get(const QUrl &url) { QByteArray header = m_oauth->createParametersString(url.toEncoded(), QOAuth::GET, m_token, m_tokenSecret, QOAuth::HMAC_SHA1, QOAuth::ParamMap(), QOAuth::ParseForHeaderArguments); QNetworkRequest request(url); request.setRawHeader("Authorization", header); return m_manager->get(request); }
ããã§ã軜ãããŒãã§ã tomboy apiã®å®è£ ãéå§ã§ããŸãã
qmlããã®äœæ¥ãç°¡åã«ããããã«ãåããŒããåå¥ã®QObjectãšããŠæ瀺ããããšã«ããQtã©ãã®ãªãŒãã³ã¹ããŒã¹ã§èŠã€ãã£ãQObjectListModelãä»ããŠããŒãã®ãªã¹ããå®è£ ããŸããã åããŒãã«ã¯ç¬èªã®GUIDããããã©ã®ããŒãã䜿çšã§ããããããããŸãã Guidã¯ã¯ã©ã€ã¢ã³ãåŽã§çæãããŸã;ãã®ãããQtã«ã¯QUuidã¯ã©ã¹ã«å¯Ÿå¿ããã¡ãœããããããŸãããããã£ãŠãæ°ããããŒããäœæããéã«ãäžæã®èå¥åãçæããå¿ èŠããããŸãããã®èå¥åã¯ä»åŸåç §ããŸãã
Note::Note(Notes *notes) : QObject(notes), m_notes(notes), m_status(StatusNew), m_isMarkedForRemoral(false) { QUuid uid = QUuid::createUuid(); m_guid = uid.toString(); m_createDate = QDateTime::currentDateTime(); }
ã¡ã¢ä»ãã®åºæ¬ã¢ã¯ã·ã§ã³ïŒ
- ãµãŒããŒãšã¡ã¢ãåæãã
- æ°ããã¡ã¢ãè¿œå
- ã¡ã¢ãæŽæ°
- ã¡ã¢ãåé€
ãããã®ã¢ã¯ã·ã§ã³ã«åºã¥ããŠãAPIãèšèšããããŒãã®ã¢ãã«ã§syncã¡ãœãããäœæããããŒãèªäœã§ã¡ãœãããä¿åãåé€ããŸãã ãããŠãã¡ãããã¿ã€ãã«ãšã³ã³ãã³ãã®ããããã£ãå®è£ ããŸãïŒ
class Note : public QObject { Q_OBJECT Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) Q_PROPERTY(QString content READ content WRITE setContent NOTIFY textChanged) Q_PROPERTY(int revision READ revision NOTIFY revisionChanged) Q_PROPERTY(Status status READ status NOTIFY statusChanged) Q_PROPERTY(QDateTime createDate READ createDate NOTIFY createDateChanged) ...
ãŸããqmlã®ç¶æ ã§äœ¿çšã§ããããŒãã¹ããŒã¿ã¹ããããã£ãè¿œå ããããšããå§ãããŸãã
Q_ENUMS(Status) public: enum Status { StatusNew, StatusActual, StatusOutdated, StatusSyncing, StatusRemoral };
ãããè¡ãã«ã¯ã転éçšã®ã¡ã¿æ å ±ãçæããããžãã¯ãã¯ãQ_ENUMSã䜿çšããŸãã ããã§ãqmlã³ãŒãã§æ°å€ãååŸããçžäºã«æ¯èŒã§ããŸãã
State { name: "syncing" when: note.status === Note.StatusSyncing
䟿å©ã§èªã¿ããããé«éã ããã§ããæååã§ã¯ãªãæ°å€ãæ¯èŒãããŸãïŒ
ããã©ã«ãã§ã¯ãQObjectListModelã§ã¯ãããªã²ãŒãããã®ã¢ãã«èŠçŽ ã¯ååãªããžã§ã¯ãã«ãã£ãŠã¢ã¯ã»ã¹ã§ããŸãããããã¯ããŸãç§ã«åããªãã®ã§ãã¢ãã«ããç¶æ¿ããObjectRoleããŒã«ã®ååãã¡ã¢ã«å€æŽããŸããã
NotesModel::NotesModel(QObject *parent) : QObjectListModel(parent) { QHash<int, QByteArray> roles; roles[ObjectRole] = "note"; setRoleNames(roles); }
次ã«ãqmlã¢ãžã¥ãŒã«èªäœã®äœæãæ€èšããŸãã APIå®è£ ãqmlã®ã€ã³ããŒãã§äœ¿çšããã«ã¯ãQDeclarativeExtensionPluginããç¶æ¿ããã¢ãžã¥ãŒã«ã«ã¯ã©ã¹ãäœæãããã®äžã«registerTypesã¡ãœãããå®è£ ããŠããã¹ãŠã®ã¡ãœãããšã¯ã©ã¹ãç»é²ããå¿ èŠããããŸãã
void QmlBinding::registerTypes(const char *uri) { Q_ASSERT(uri == QLatin1String("com.ubuntu.one")); qmlRegisterType<UbuntuOneApi>(uri, 1, 0, "Api"); qmlRegisterType<ProgressIndicatorBase>(uri, 1, 0, "ProgressIndicatorBase"); qmlRegisterUncreatableType<Notes>(uri, 1, 0, "Notes", tr("Use Api.notes property")); qmlRegisterUncreatableType<Account>(uri, 1, 0, "Account", tr("Use Api.account property")); qmlRegisterUncreatableType<Note>(uri, 1, 0, "Note", tr("")); qmlRegisterUncreatableType<NotesModel>(uri, 1, 0, "NotesModel", tr("")); } Q_EXPORT_PLUGIN2(qmlbinding, QmlBinding)
ããªãã¯ããããæèšã«æ°ã¥ããå°ããããšæãã§ãããã ãããŠããã®uriã¯ã©ãããæ¥ãã®ã§ããïŒ ãŸããã¢ãžã¥ãŒã«ãååšãããã£ã¬ã¯ããªã®ååããååŸãããŸãã ã€ãŸããQtã¯æ¬¡ã®ã¢ãžã¥ãŒã«ãæ¢ããŸãã
$QML_IMPORTS_DIR/com/ubuntu/one/
ããããããã ãã§ã¯ãããŸããã Qtãã¢ãžã¥ãŒã«ãèŠã€ããŠã€ã³ããŒãããã«ã¯ããã£ã¬ã¯ããªã«ãã€ããªãã©ã°ã€ã³ãqmlãjsãã¡ã€ã«ããªã¹ããããæ£ããæ§æãããqmldirãã¡ã€ã«ãå«ãŸããŠããå¿ èŠããããŸãã
plugin qmlbinding
Meego Harmattançšã®qmlã€ã³ã¿ãŒãã§ã€ã¹ã®éçº
Meegoã®ã¢ããªã±ãŒã·ã§ã³ã®å€§éšåã¯PageStackWindowèŠçŽ ã§ãããã¯å¥åŠãªããšã«ãããŒãžã®ã¹ã¿ãã¯ã§ãã ããŒãžã¯pushã¡ãœããã䜿çšããŠã¹ã¿ãã¯ã«ããã·ã¥ãããpopãââ䜿çšããŠããããããŸãã ããŒãžã®1ã€ããœãŒã¹ãšããŠå²ãåœãŠãå¿ èŠããããŸãã åããŒãžã«ã¯ç¬èªã®ããŒã«ããŒããããŸãã åãããŒãžã«è€æ°ã®ããŒãžãå²ãåœãŠãããšãã§ããŸãã
import QtQuick 1.1 import com.nokia.meego 1.0 import com.ubuntu.one 1.0 // notes API PageStackWindow { id: appWindow initialPage: noteListPage Api { //, API id: api Component.onCompleted: checkToken() onHasTokenChanged: checkToken() function checkToken() { if (!hasToken) loginPage.open(); else api.notes.sync(); } } ...
ããã§ãå¿ èŠãªãã¹ãŠã®ããŒãžãšãã¡ã¢ãè¿œå ãããã¿ã³ãšã¢ã¯ã·ã§ã³ãå«ãã¡ãã¥ãŒãããæšæºããŒã«ããŒãäœæããŸãã
... LoginPage { id: loginPage onAccepted: api.requestToken(email, password); } NoteListPage { id: noteListPage notes: api.notes } NoteEditPage { id: noteEditPage } AboutPage { id: aboutPage } ToolBarLayout { id: commonTools visible: true ToolIcon { iconId: "toolbar-add" onClicked: { noteEditPage.note = api.notes.create(); pageStack.push(noteEditPage); } } ToolIcon { platformIconId: "toolbar-view-menu" anchors.right: (parent === undefined)? undefined: parent.right onClicked: (menu.status === DialogStatus.Closed)? menu.open(): menu.close() } } Menu { id: menu visualParent: pageStack MenuLayout { MenuItem { text: qsTr("About") onClicked: {menu.close(); pageStack.push(aboutPage)} } MenuItem { text: qsTr("Sync") onClicked: api.notes.sync(); } MenuItem { text: api.hasToken ? qsTr("Logout") : qsTr("Login") onClicked: { if (api.hasToken) api.purge(); else loginPage.open(); } } } }
次ã«ãNoteListPage.qmlã«å®è£ ãããŠããNoteListPageã®äŸã䜿çšããŠãå¥ã®ããŒãžãã©ã®ãããªãã®ããèŠãŠã¿ãŸãããã
import QtQuick 1.1 import com.nokia.meego 1.0 import com.ubuntu.one 1.0 Page { id: noteListPage property QtObject notes: null tools: commonTools // , main.qml PageHeader { // . id: header text: qsTr("Notes:") } ListView { id: listView anchors.top: header.bottom anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: 11 clip: true focus: true model: notes.model delegate: ItemDelegate { title: note.title // subtitle: truncate(note.content, 32) onClicked: { noteEditPage.note = note; pageStack.push(noteEditPage); // } function truncate(str, n, suffix) { str = str.replace(/\r\n/g, ""); if (suffix === undefined) suffix = "..."; if (str.length > n) str = str.substring(0, n) + suffix; return str; } } } ScrollDecorator { flickableItem: listView } }
çµæã¯ãšãŠãããããããŒãžã§ãïŒ
ãã°ã€ã³ãŠã£ã³ããŠã«ã¯ãSheetãªããžã§ã¯ãã䜿çšããŸãããããã¯ãäžéšãããããã¢ããããããŒãžã§ãã éåžžããããå©çšããŠããŠãŒã¶ãŒã¯æ å ±ãæ±ããããŸãã
import QtQuick 1.0 import com.nokia.meego 1.0 import "constants.js" as UI // - js . namespace' qml'. Sheet { id: loginPage property alias email: loginInput.text //. , loginInput.text property alias password: passwordInput.text content: Column { // sheet' anchors.topMargin: UI.MARGIN_DEFAULT anchors.horizontalCenter: parent.horizontalCenter Image { id: logo source: "images/UbuntuOneLogo.svg" } Text { id: loginTitle width: parent.width text: qsTr("Email:") font.pixelSize: UI.FONT_DEFAULT_SIZE color: UI.LIST_TITLE_COLOR } TextField { id: loginInput width: parent.width } Text { id: passwordTitle width: parent.width text: qsTr("Password:") font.pixelSize: UI.FONT_DEFAULT_SIZE color: UI.LIST_TITLE_COLOR } TextField { id: passwordInput width: parent.width echoMode: TextInput.Password } } acceptButtonText: qsTr("Login") rejectButtonText: qsTr("Cancel") }
ãã®çŽ æŽãããã¯ãã¹ãŠæ¬¡ã®ããã«ãªããŸãã
ç·šéããã³ããŒãžã«ã€ããŠã¯ãã¡ã¢ã®ãªã¹ãã«æ»ãããã®æ»ããã¿ã³ãå®è£ ããå¿ èŠããããŸãã CommonToolsã¯ããã«ã¯ãã¯ãé©åã§ã¯ãªããç¬èªã®ããŒã«ããŒãå¿ èŠã§ãã
ToolBarLayout { id: aboutTools visible: true ToolIcon { iconId: "toolbar-back" onClicked: { pageStack.pop() } } }
ã©ã³ãã£ãŒã¢ã€ã³ã³
ã¢ããªã±ãŒã·ã§ã³ã«èµ·åã¢ã€ã³ã³ãèšå®ããã«ã¯ããã¹ãŠã®linuxoids .desktopãã¡ã€ã«ã«éŠŽæã¿ã®ãããã¡ã€ã«ãäœæããŸãã
[Desktop Entry] Name=ubuntuNotes Name[ru]=ubuntuNotes GenericName=ubuntuNotes GenericName[ru]=ubuntuNotes Comment=Notes editor with sync Comment[ru]= Exec=/usr/bin/single-instance /opt/ubuntunotes/bin/ubuntuNotes %U Icon=/usr/share/icons/hicolor/80x80/apps/ubuntuNotes.png StartupNotify=true Terminal=false Type=Application Categories=Network;Qt;
Execã»ã¯ã·ã§ã³ã«æ³šæããŠãã ããããã®ããã«ãã¢ããªã±ãŒã·ã§ã³ãæ°åèµ·åããããšã¯ã§ããŸããã ã¢ããªã±ãŒã·ã§ã³ã«çŸããã¹ãã©ãã·ã¥ãæããããå Žåã¯ãinvokerãŠãŒãã£ãªãã£ã䜿çšã§ããŸãã
Exec=/usr/bin/invoker --splash=/usr/share/apps/qutim/declarative/meego/qutim-portrait.png --splash-landscape=/usr/share/apps/qutim/declarative/meego/qutim-landscape.png --type=e /usr/bin/qutim
ãã¡ãããçŸããã¢ã€ã³ã³ã§ã¯ãªãããã¹ãŠã®åçãå¥ã®å Žæã«èšå®ããããšãå¿ããªãã§ãã ãããèµ€ãåè§ã衚瀺ãããŸãã
ãã«ãdebããã±ãŒãž
ã¢ã»ã³ããªã«ã¯ãæšæºã®dpkg-buildpackageãšéåžžã®debianã䜿çšãããŸããããã¯äŸ¿å®äždebian_harmattanãšåŒã°ããã¢ã»ã³ããªã®åã«ã·ã³ããªãã¯ãªã³ã¯debian_harmattan> debianãèšå®ãããŸãã å¶åŸ¡ã»ã¯ã·ã§ã³ã¯debianããã±ãŒãžã®æšæºã§ããããã®äœæã«ã€ããŠã¯ãã§ã«Habréã®å€ãã®èšäºã§è©³ãã説æãããŠããŸãã ãã®äžé£ã®èšäºãèªãããšããå§ãããŸãã
å¶åŸ¡ãã¡ã€ã«ã®å 容ïŒ
Source: ubuntunotes Section: user/network Priority: extra Maintainer: Aleksey Sidorov <gorthauer87@ya.ru> Build-Depends: debhelper (>= 5),locales,cmake, libgconf2-6,libssl-dev,libxext-dev,libqt4-dev,libqca2-dev,libqca2-plugin-ossl, libqtm-dev Standards-Version: 3.7.2 Package: ubuntunotes Section: user/network Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends},libqca2-plugin-ossl Description: TODO XSBC-Maemo-Display-Name: ubuntuNotes XSBC-Bugtracker: https://github.com/gorthauer/ubuntu-one-qml Package: ubuntunotes-dbg Section: debug Priority: extra Architecture: any Depends: ${misc:Depends}, qutim (= ${binary:Version}) Description: Debug symbols for ubuntuNotes Debug symbols to provide extra debug info in case of crash.
å€æŽãã°ãç¶æããããã«ãdevscriptsããã±ãŒãžããdchããã°ã©ã ãã€ã³ã¹ããŒã«ããã®ã¯é©åã§ãã 䜿ãæ¹ã¯ãšãŠãç°¡åã§ãã
$ dch - i
ã«ãŒã«ãã¡ã€ã«ã¯ãdebhelper'ovã®äœ¿çšã®ãããã§ãéåžžã«ç°¡åã§ããã
#!/usr/bin/make -f %: dh $@ override_dh_auto_configure: dh_auto_configure -- -DCMAKE_INSTALL_PREFIX=/opt/ubuntunotes -DHARMATTAN=ON override_dh_auto_install: dh_auto_install --destdir=$(CURDIR)/debian/ubuntunotes
åããã¡ã€ã«ã¯ãæå°éã®å€æŽã§ã»ãšãã©ãã¹ãŠã®ãããžã§ã¯ãã«é©ããŠããŸãã
ããã±ãŒãžã®äœæãç°¡åã§ãã
$ ln -s ./debian_harmattan ./debian $ dpkg-buildpackage -b
ãããã«
ããã§ãçµæã®ããã±ãŒãžãå®å šã«ã€ã³ã¹ããŒã«ããŠå®è¡ããé«éã§å¿çæ§ã®é«ãã€ã³ã¿ãŒãã§ãŒã¹ã楜ããããšãã§ããŸãã èªå·±ã¢ã»ã³ããªã®ãœãŒã¹ã³ãŒãã¯githubããããŠã³ããŒãã§ããŸãã ã³ã³ãã€ã«æžã¿ã®debããã±ãŒãžããããŸã ã ãã®èšäºããHarmattanã®åå¿è ããããããŒã®å©ãã«ãªããæåã®ã¢ããªã±ãŒã·ã§ã³ã®äœæãããæ©ãå§ããããšãé¡ã£ãŠããŸãã å°æ¥çã«ã¯ãããããç§ã¯Habrasocietyã«cmakeã䜿ãããšã®åŸ®åŠããããè¯ã説æããããšããã§ããããå€ãã®äººã¯ãã§ã«åœŒã«é¢ããèšäºããªãããšã«äžæºãèšã£ãŠããŸãã