diff --git a/ionicons/alert.svg b/ionicons/alert.svg new file mode 100644 index 0000000..f0c4e2c --- /dev/null +++ b/ionicons/alert.svg @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/ionicons/arrow-up-c.svg b/ionicons/arrow-up-c.svg new file mode 100644 index 0000000..b0398ed --- /dev/null +++ b/ionicons/arrow-up-c.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/ionicons/chatbox.svg b/ionicons/chatbox.svg new file mode 100644 index 0000000..0c2a7e7 --- /dev/null +++ b/ionicons/chatbox.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/ionicons/chatboxes.svg b/ionicons/chatboxes.svg new file mode 100644 index 0000000..dba6e29 --- /dev/null +++ b/ionicons/chatboxes.svg @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/ionicons/chatbubble.svg b/ionicons/chatbubble.svg new file mode 100644 index 0000000..5c3148f --- /dev/null +++ b/ionicons/chatbubble.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/ionicons/chatbubbles.svg b/ionicons/chatbubbles.svg new file mode 100644 index 0000000..8cc5f34 --- /dev/null +++ b/ionicons/chatbubbles.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/ionicons/earth.svg b/ionicons/earth.svg new file mode 100644 index 0000000..078e7f7 --- /dev/null +++ b/ionicons/earth.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + diff --git a/ionicons/eye-disabled.svg b/ionicons/eye-disabled.svg new file mode 100644 index 0000000..7a270cb --- /dev/null +++ b/ionicons/eye-disabled.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/ionicons/eye.svg b/ionicons/eye.svg new file mode 100644 index 0000000..6b64633 --- /dev/null +++ b/ionicons/eye.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/ionicons/heart.svg b/ionicons/heart.svg new file mode 100644 index 0000000..34aa83d --- /dev/null +++ b/ionicons/heart.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/ionicons/image.svg b/ionicons/image.svg new file mode 100644 index 0000000..b33d4ea --- /dev/null +++ b/ionicons/image.svg @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/ionicons/images.svg b/ionicons/images.svg new file mode 100644 index 0000000..708c415 --- /dev/null +++ b/ionicons/images.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/ionicons/loop.svg b/ionicons/loop.svg new file mode 100644 index 0000000..865781e --- /dev/null +++ b/ionicons/loop.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/ionicons/paper-airplane.svg b/ionicons/paper-airplane.svg new file mode 100644 index 0000000..fc5fb14 --- /dev/null +++ b/ionicons/paper-airplane.svg @@ -0,0 +1,13 @@ + + + + + + + diff --git a/ionicons/paperclip.svg b/ionicons/paperclip.svg new file mode 100644 index 0000000..6c21efb --- /dev/null +++ b/ionicons/paperclip.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/ionicons/person-stalker.svg b/ionicons/person-stalker.svg new file mode 100644 index 0000000..cc47173 --- /dev/null +++ b/ionicons/person-stalker.svg @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/ionicons/person.svg b/ionicons/person.svg new file mode 100644 index 0000000..0b305ce --- /dev/null +++ b/ionicons/person.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/ionicons/pin.svg b/ionicons/pin.svg new file mode 100644 index 0000000..f68b9f6 --- /dev/null +++ b/ionicons/pin.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/ionicons/pricetag.svg b/ionicons/pricetag.svg new file mode 100644 index 0000000..21624e2 --- /dev/null +++ b/ionicons/pricetag.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/ionicons/pricetags.svg b/ionicons/pricetags.svg new file mode 100644 index 0000000..9294f0e --- /dev/null +++ b/ionicons/pricetags.svg @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/ionicons/refresh.svg b/ionicons/refresh.svg new file mode 100644 index 0000000..1e2d80e --- /dev/null +++ b/ionicons/refresh.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/ionicons/reply.svg b/ionicons/reply.svg new file mode 100644 index 0000000..d08d582 --- /dev/null +++ b/ionicons/reply.svg @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/ionicons/share.svg b/ionicons/share.svg new file mode 100644 index 0000000..0030b8a --- /dev/null +++ b/ionicons/share.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/ionicons/star.svg b/ionicons/star.svg new file mode 100644 index 0000000..3c4b403 --- /dev/null +++ b/ionicons/star.svg @@ -0,0 +1,7 @@ + + + + + + diff --git a/ionicons/trash-a.svg b/ionicons/trash-a.svg new file mode 100644 index 0000000..ec2afc2 --- /dev/null +++ b/ionicons/trash-a.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..ce25db0 --- /dev/null +++ b/main.cpp @@ -0,0 +1,42 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#include "saoriwindow.h" +#include "saoriapplication.h" +#include +#include + +int main(int argc, char *argv[]) +{ + SaoriApplication a(argc, argv); + QTranslator translator; + translator.load(":/lang/saori.qm"); + a.installTranslator(&translator); + + SaoriWindow w; + w.show(); + return a.exec(); +} diff --git a/saori.pro b/saori.pro new file mode 100644 index 0000000..a16a457 --- /dev/null +++ b/saori.pro @@ -0,0 +1,55 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2017-11-20T07:19:06 +# +#------------------------------------------------- + +QT += core gui network + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = saori +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which as been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp \ + saoriwindow.cpp \ + saoridon.cpp \ + saoriview.cpp \ + saoriaddaccountdialog.cpp \ + saoriaccount.cpp \ + saoriapplication.cpp + +HEADERS += \ + saoriwindow.h \ + saoridon.h \ + saoriview.h \ + saoriaddaccountdialog.h \ + saoridef.h \ + saoriaccount.h \ + saoriapplication.h + +FORMS += \ + saoriwindow.ui \ + saoriview.ui \ + saoriaddaccountdialog.ui + +TRANSLATIONS += \ + saori_ja.ts + +RESOURCES += \ + saori.qrc + +DISTFILES += \ + saori_ja.ts diff --git a/saori.qrc b/saori.qrc new file mode 100644 index 0000000..fb65ba0 --- /dev/null +++ b/saori.qrc @@ -0,0 +1,30 @@ + + + + ionicons/heart.svg + ionicons/trash-a.svg + ionicons/paperclip.svg + ionicons/paper-airplane.svg + ionicons/chatboxes.svg + ionicons/images.svg + ionicons/image.svg + ionicons/earth.svg + ionicons/eye-disabled.svg + ionicons/eye.svg + ionicons/star.svg + ionicons/pricetags.svg + ionicons/pricetag.svg + ionicons/person.svg + ionicons/person-stalker.svg + ionicons/chatbubbles.svg + ionicons/alert.svg + ionicons/pin.svg + ionicons/refresh.svg + ionicons/loop.svg + ionicons/chatbox.svg + ionicons/arrow-up-c.svg + ionicons/chatbubble.svg + ionicons/share.svg + ionicons/reply.svg + + diff --git a/saori_ja.ts b/saori_ja.ts new file mode 100644 index 0000000..7e676a5 --- /dev/null +++ b/saori_ja.ts @@ -0,0 +1,203 @@ + + + + + SaoriAddAccountDialog + + + Add new Account + + + + + Instance URL: + + + + + Get Access token: + + + + + Open Authorize page: + + + + + Check + + + + + Get! + + + + + Authorize Code: + + + + + Open WebBrowser + + + + + Account: + + + + + SaoriView + + + Form + + + + + Pin + + + + + Notify + + + + + Auto reload + + + + + Newest + + + + + Reload + + + + + Toot + + + + + SaoriWindow + + + SaoriWindow + + + + + &File + ファイル(&F) + + + + &View + 表示(&V) + + + + &Edit + 編集(&E) + + + + &Help + ヘルプ(&H) + + + + Timeline &list + タイムラインリスト(&l) + + + + Auto reload Interval (minutes) + + + + + List + リスト + + + + Account + + + + + Instance + + + + + &Quit + + + + + Show/Hide Timeline &List + + + + + &Open Timeline + + + + + &Add Account + + + + + &Remove Account + + + + + Accounts + アカウント + + + + home + ホーム + + + + local + ローカルタイムライン + + + + public + 連合タイムライン + + + + notifications + 通知 + + + + Instances + インスタンス + + + + Infomation + 情報 + + + diff --git a/saoriaccount.cpp b/saoriaccount.cpp new file mode 100644 index 0000000..201ba0f --- /dev/null +++ b/saoriaccount.cpp @@ -0,0 +1,108 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#include "saoriaccount.h" +#include "saoridef.h" + +SaoriAccount::SaoriAccount(const QString accountName, Saoridon *instance, const QString accsessToken, QObject *parent) : QObject(parent) +{ + m_name = accountName; + m_accessToken = accsessToken; + m_instance = instance; + getAccountInfomation(); +} + +const QString SaoriAccount::accessToken() +{ + return m_accessToken; +} + +void SaoriAccount::setAccessToken(QString token) +{ + m_accessToken = token; + return; +} + +const QString SaoriAccount::name() +{ + return m_name; +} + +void SaoriAccount::setName(const QString name) +{ + m_name = name; + return; +} + +Saoridon *SaoriAccount::instance() +{ + return m_instance; +} + +void SaoriAccount::getAccountInfomation() +{ + auto manager = new QNetworkAccessManager(); + QNetworkRequest request = createHearder(); + request.setUrl(QUrl(m_instance->instance().url() + SAORI_MASTODON_APIPATH_ACCOUNTS + "/verify_credentials")); + auto *reply = manager->get(request); + connect(manager,&QNetworkAccessManager::finished,[=](){ + if (reply->NoError == QNetworkReply::NoError) { + QJsonObject json = QJsonDocument::fromJson(reply->readAll()).object(); + QMap info; + for(auto it = json.begin();it != json.end();it ++) { + info[it.key()] = it.value().toString(); + } + m_accountInfo = info; + emit accountInfomationChanged(); + } + manager->deleteLater(); + }); + return; +} + +QNetworkRequest SaoriAccount::createHearder() +{ + QNetworkRequest request; + request.setRawHeader("Authorization","Bearer " + accessToken().toLatin1()); + return request; +} + +const QString SaoriAccount::accountInfo(const QString key) +{ + return m_accountInfo[key]; +} + +const QStringList SaoriAccount::timelineList() +{ + QStringList tl; + tl << "home" + << "local" + << "public" + << "notifications" + ; + return tl; + +} diff --git a/saoriaccount.h b/saoriaccount.h new file mode 100644 index 0000000..6adbb17 --- /dev/null +++ b/saoriaccount.h @@ -0,0 +1,72 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#ifndef SAORIACCOUNT_H +#define SAORIACCOUNT_H + +#include +#include +#include +#include +#include +#include +#include + +class SaoriAccount : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString accessToken READ accessToken WRITE setAccessToken NOTIFY accessTokenChanged) + +public: + explicit SaoriAccount(const QString accountName, Saoridon *instance, const QString accsessToken, QObject *parent = nullptr); + const QString accessToken(); + void setAccessToken(QString token); + const QString name(); + void setName(const QString name); + Saoridon *instance(); + const QString accountInfo(const QString key); + const QStringList timelineList(); + +protected: + void getAccountInfomation(); + QNetworkRequest createHearder(); + void requestGET(QUrl url,QNetworkAccessManager *manager); + +protected: + QString m_name; + QString m_accessToken; + Saoridon *m_instance; + QMap m_accountInfo; + +signals: + void accessTokenChanged(QString); + void accountInfomationChanged(); + +public slots: +}; + +#endif // SAORIACCOUNT_H diff --git a/saoriaddaccountdialog.cpp b/saoriaddaccountdialog.cpp new file mode 100644 index 0000000..828f04a --- /dev/null +++ b/saoriaddaccountdialog.cpp @@ -0,0 +1,112 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#include "saoriaddaccountdialog.h" +#include "saoriapplication.h" +#include "saoridef.h" +#include "ui_saoriaddaccountdialog.h" +#include +#include +#include +#include +#include +#include +#include +#include + +SaoriAddAccountDialog::SaoriAddAccountDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::SaoriAddAccountDialog) +{ + ui->setupUi(this); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + for(int i = 0;i < SaoriApplication::getInstanceList()->count();i ++) { + ui->instanceUrl_comboBox->addItem(SaoriApplication::getInstanceList()->at(i)->instance().toString()); + } + ui->getAccessToken_pushButton->setEnabled(false); + ui->authorizeCode_lineEdit->setEnabled(false); + connect(ui->instanceUrl_comboBox,&QComboBox::editTextChanged,[this](QString) { + m_instance = SaoriApplication::findInstance(ui->instanceUrl_comboBox->currentText()); + if (m_instance != nullptr) ui->openWebBrowser_pushButton->setEnabled(true); + else ui->openWebBrowser_pushButton->setEnabled(false); + }); +} + +SaoriAddAccountDialog::~SaoriAddAccountDialog() +{ + delete ui; +} + +void SaoriAddAccountDialog::on_openWebBrowser_pushButton_clicked() +{ + m_instance = SaoriApplication::findInstance(ui->instanceUrl_comboBox->currentText()); + if (m_instance == nullptr) return; + if (m_instance->clientId().isEmpty() || m_instance->clientSecret().isEmpty()) { + qDebug() << "regist"; + } + QDesktopServices::openUrl(m_instance->getAuthorizedUrl()); + QString text = ui->instanceUrl_comboBox->currentText(); + ui->instanceUrl_comboBox->clear(); + ui->instanceUrl_comboBox->addItem(text); + ui->instanceUrl_comboBox->setEditable(false); + ui->openWebBrowser_pushButton->setEnabled(false); + ui->getAccessToken_pushButton->setEnabled(true); + ui->authorizeCode_lineEdit->setEnabled(true); + return; +} + +void SaoriAddAccountDialog::on_getAccessToken_pushButton_clicked() +{ + if (ui->authorizeCode_lineEdit->text().isEmpty()) return; + QString token = m_instance->getAccessToken(ui->authorizeCode_lineEdit->text()); + if (token.isEmpty()) return; + m_account = new SaoriAccount("check",m_instance,token); + + auto manager = new QNetworkAccessManager(); + QEventLoop event; + connect(manager,&QNetworkAccessManager::finished,&event,&QEventLoop::quit); + QUrlQuery params; + QNetworkRequest request; + QString instance = m_instance->instanceInfo("uri"); + + request.setRawHeader("Authorization","Bearer " + token.toLatin1()); + request.setUrl(QUrl(m_instance->instance().url() + SAORI_MASTODON_APIPATH_ACCOUNTS + "/verify_credentials")); + auto reply = manager->get(request); + event.exec(); + if (reply->error() != QNetworkReply::NoError) { + manager->deleteLater(); + return; + } + QJsonObject json = QJsonDocument::fromJson(reply->readAll()).object(); + QString account = json["acct"].toString(); + manager->deleteLater(); + + m_account->setName(account + "@" + instance); + ui->account_lineEdit->setText(m_account->name()); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + return; + +} diff --git a/saoriaddaccountdialog.h b/saoriaddaccountdialog.h new file mode 100644 index 0000000..ad5c13c --- /dev/null +++ b/saoriaddaccountdialog.h @@ -0,0 +1,59 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#ifndef SAORIADDACCOUNTDIALOG_H +#define SAORIADDACCOUNTDIALOG_H + +#include +#include +#include + +namespace Ui { +class SaoriAddAccountDialog; +} + +class SaoriAddAccountDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SaoriAddAccountDialog(QWidget *parent = 0); + ~SaoriAddAccountDialog(); + +public: + Saoridon *m_instance; + SaoriAccount *m_account; + +private slots: + void on_openWebBrowser_pushButton_clicked(); + + void on_getAccessToken_pushButton_clicked(); + +private: + Ui::SaoriAddAccountDialog *ui; +}; + +#endif // SAORIADDACCOUNTDIALOG_H diff --git a/saoriaddaccountdialog.ui b/saoriaddaccountdialog.ui new file mode 100644 index 0000000..11d3d82 --- /dev/null +++ b/saoriaddaccountdialog.ui @@ -0,0 +1,154 @@ + + + SaoriAddAccountDialog + + + + 0 + 0 + 511 + 272 + + + + Add new Account + + + + + + + + Instance URL: + + + + + + + Get Access token: + + + + + + + Open Authorize page: + + + + + + + Authorize Code: + + + + + + + true + + + + + + + Account: + + + + + + + true + + + + + + + Check + + + + + + + Open WebBrowser + + + + + + + + + + Get! + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + SaoriAddAccountDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SaoriAddAccountDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/saoriapplication.cpp b/saoriapplication.cpp new file mode 100644 index 0000000..2fdd9d7 --- /dev/null +++ b/saoriapplication.cpp @@ -0,0 +1,149 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#include "saoriapplication.h" +#include "saoridef.h" +#include +#include +#include +#include + +SaoriApplication *SaoriApplication::m_self = nullptr; + +SaoriApplication::SaoriApplication(int &argc, char **argv) + :QApplication(argc, argv, true) +{ + m_self = this; + setOrganizationName(SAORI_QSETTINGS_ORGANIZATION); + setOrganizationDomain(SAORI_QSETTINGS_DOMAIN); + setApplicationName(SAORI_QSETTINGS_APPLICATION); + + m_config = new QSettings(SAORI_QSETTINGS_DOMAIN,SAORI_QSETTINGS_APPLICATION,this); + + loadSettings(); + + QDir dir; + if (!dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))) { + // CacheLocation is not writable. + } +} + +SaoriApplication::~SaoriApplication() +{ + saveInstancesSettings(); + saveAccountsSettings(); +} + +Saoridon *SaoriApplication::findInstance(QUrl instance) +{ + for(int i = 0;i < getInstanceList()->count();i ++) { + if (getInstanceList()->at(i)->instance() == instance) return getInstanceList()->at(i); + break; + } + return nullptr; +} + +SaoriAccount *SaoriApplication::findAccount(QString account) +{ + for(int i = 0;i < getAccountList()->count();i ++) { + if (getAccountList()->at(i)->name() == account) return getAccountList()->at(i); + break; + } + return nullptr; +} + +QList *SaoriApplication::getInstanceList() +{ + return &m_self->m_instanceList; +} + +QList *SaoriApplication::getAccountList() +{ + return &m_self->m_accountList; +} + +SaoriApplication *SaoriApplication::saori() +{ + return m_self; +} + +void SaoriApplication::loadSettings() +{ + m_config->beginGroup("instances"); + auto instances = m_config->childGroups(); + for(int i = 0;i < instances.count();i ++) { + m_config->beginGroup(instances[i]); + auto *instance = new Saoridon(m_config->value("url").toUrl(),this); + instance->setClientId(m_config->value("clientId").toString()); + instance->setClientSecret(m_config->value("clientSecret").toString()); + m_instanceList.append(instance); + m_config->endGroup(); + } + m_config->endGroup(); + + m_config->beginGroup("accounts"); + auto accounts = m_config->childGroups(); + for(int i = 0;i < accounts.count();i ++) { + m_config->beginGroup(accounts[i]); + auto *account = new SaoriAccount(accounts[i], + findInstance(m_config->value("instance").toUrl()), + m_config->value("accessToken").toString(), + this); + m_accountList.append(account); + m_config->endGroup(); + } + m_config->endGroup(); + +} + +void SaoriApplication::saveInstancesSettings() +{ + m_config->remove("instances"); + m_config->beginGroup("instances"); + for(int i = 0;i < m_instanceList.count();i ++) { + m_config->beginGroup(QCryptographicHash::hash(m_instanceList[i]->instance().toString().toLatin1(),QCryptographicHash::Md5)); + m_config->setValue("url",m_instanceList[i]->instance()); + m_config->setValue("clientId",m_instanceList[i]->clientId()); + m_config->setValue("clientSecret",m_instanceList[i]->clientSecret()); + m_config->endGroup(); + } + m_config->endGroup(); + m_config->sync(); +} + +void SaoriApplication::saveAccountsSettings() +{ + m_config->remove("accounts"); + m_config->beginGroup("accounts"); + for(int i = 0;i < m_accountList.count();i ++) { + m_config->beginGroup(m_accountList[i]->name()); + m_config->setValue("instance",m_accountList[i]->instance()->instance()); + m_config->setValue("accessToken",m_accountList[i]->accessToken()); + m_config->endGroup(); + } + m_config->endGroup(); + m_config->sync(); +} diff --git a/saoriapplication.h b/saoriapplication.h new file mode 100644 index 0000000..9d73de0 --- /dev/null +++ b/saoriapplication.h @@ -0,0 +1,65 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#ifndef SAORIAPPLICATION_H +#define SAORIAPPLICATION_H + +#include +#include +#include +#include +#include + +class SaoriApplication : public QApplication +{ + Q_OBJECT +public: + SaoriApplication(int &argc, char **argv); + ~SaoriApplication(); + static Saoridon *findInstance(QUrl instance); + static SaoriAccount *findAccount(QString account); + static QList * getInstanceList(); + static QList * getAccountList(); + static SaoriApplication * saori(); + +protected: + QSettings *m_config; + QList m_instanceList; + QList m_accountList; + static SaoriApplication *m_self; + +protected: + void loadSettings(); + void saveInstancesSettings(); + void saveAccountsSettings(); + +public slots: + +signals: + +}; + +#endif // SAORIAPPLICATION_H diff --git a/saoridef.h b/saoridef.h new file mode 100644 index 0000000..234bd60 --- /dev/null +++ b/saoridef.h @@ -0,0 +1,46 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#ifndef SAORIDEF_H +#define SAORIDEF_H + +#define SAORI_CLIENT_NAME "Saori Mastodon Client" +#define SAORI_CLIENT_REDIRECT_URI "urn:ietf:wg:oauth:2.0:oob" +#define SAORI_CLIENT_SCOPES "read write follow" +#define SAORI_CLIENT_WEBSITE "https://dev.net-p.org/tamra/saori/wiki" +#define SAORI_QSETTINGS_ORGANIZATION "nop" +#define SAORI_QSETTINGS_DOMAIN "net-p.org" +#define SAORI_QSETTINGS_APPLICATION "Saori" + +#define SAORI_MASTODON_APIPATH_APPS "/api/v1/apps" +#define SAORI_MASTODON_APIPATH_AUTHORIZE "/oauth/authorize" +#define SAORI_MASTODON_APIPATH_TOKEN "/oauth/token" +#define SAORI_MASTODON_APIPATH_INSTANCE "/api/v1/instance" +#define SAORI_MASTODON_APIPATH_ACCOUNTS "/api/v1/accounts" +#define SAORI_MASTODON_APIPATH_TIMELINE "/api/v1/timeline" + + +#endif // SAORIDEF_H diff --git a/saoridon.cpp b/saoridon.cpp new file mode 100644 index 0000000..7a9f86b --- /dev/null +++ b/saoridon.cpp @@ -0,0 +1,182 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#include "saoridon.h" +#include "saoridef.h" +#include +#include +#include +#include +#include +#include +#include + +Saoridon::Saoridon(QUrl instanceUrl,QObject *parent) : QObject(parent) +{ + setInstance(instanceUrl); + getInstanceInfomation(); +} + +const QUrl Saoridon::instance() +{ + return m_instance; +} + +void Saoridon::setInstance(const QUrl instanceUrl) +{ + m_instance = instanceUrl; + return; +} + +const QString Saoridon::clientId() +{ + return m_clientId; +} + +void Saoridon::setClientId(const QString id) +{ + m_clientId = id; + return; +} + +const QString Saoridon::clientSecret() +{ + return m_clientSecret; +} + +void Saoridon::setClientSecret(const QString secret) +{ + m_clientSecret = secret; +} + +bool Saoridon::clientRedistration() +{ + auto manager = new QNetworkAccessManager(); + QEventLoop event; + connect(manager,SIGNAL(finished(QNetworkReply*)),&event,SLOT(quit())); + QUrlQuery params; + params.addQueryItem("client_name",SAORI_CLIENT_NAME); + params.addQueryItem("redirect_uris",SAORI_CLIENT_REDIRECT_URI); + params.addQueryItem("scopes",SAORI_CLIENT_SCOPES); + params.addQueryItem("website",SAORI_CLIENT_WEBSITE); + QNetworkRequest request; + request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/x-www-form-urlencoded")); + request.setUrl(QUrl(instance().url() + SAORI_MASTODON_APIPATH_APPS)); + auto *reply = manager->post(request,params.toString().toLatin1()); + event.exec(); + if (reply->error() != QNetworkReply::NoError) { + manager->deleteLater(); + return false; + } + QJsonObject json = QJsonDocument::fromJson(reply->readAll()).object(); + QString id = json["client_id"].toString(); + QString secret = json["client_secret"].toString(); + if (id.isEmpty() || secret.isEmpty()) return false; + setClientId(id); + setClientSecret(secret); + manager->deleteLater(); + return true; +} + +const QUrl Saoridon::getAuthorizedUrl() +{ + //if (clientId().isEmpty() || clientSecret().isEmpty()) return QUrl(); + QUrlQuery params; + params.addQueryItem("client_id",clientId()); + params.addQueryItem("response_type","code"); + params.addQueryItem("redirect_uri","urn:ietf:wg:oauth:2.0:oob"); + params.addQueryItem("scope",SAORI_CLIENT_SCOPES); + QUrl url = instance().url() + SAORI_MASTODON_APIPATH_AUTHORIZE; + url.setQuery(params); + return url; + + + +} + +const QString Saoridon::getAccessToken(const QString code) +{ + auto manager = new QNetworkAccessManager(); + QEventLoop event; + connect(manager,&QNetworkAccessManager::finished,&event,&QEventLoop::quit); + QUrlQuery params; + params.addQueryItem("grant_type","authorization_code"); + params.addQueryItem("redirect_uri","urn:ietf:wg:oauth:2.0:oob"); + params.addQueryItem("client_id",clientId()); + params.addQueryItem("client_secret",clientSecret()); + params.addQueryItem("code",code); + QNetworkRequest request; + request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/x-www-form-urlencoded")); + request.setUrl(QUrl(instance().url() + SAORI_MASTODON_APIPATH_TOKEN)); + auto *reply = manager->post(request,params.toString().toLatin1()); + event.exec(); + if (reply->error() != QNetworkReply::NoError) { + manager->deleteLater(); + return QString(); + } + QJsonObject json = QJsonDocument::fromJson(reply->readAll()).object(); + QString token = json["access_token"].toString(); + manager->deleteLater(); + return token; +} + +void Saoridon::getInstanceInfomation() +{ + auto manager = new QNetworkAccessManager(); + QNetworkRequest request; + request.setUrl(QUrl(instance().url() + SAORI_MASTODON_APIPATH_INSTANCE)); + auto *reply = manager->get(request); + connect(manager,&QNetworkAccessManager::finished,[=](){ + if (reply->NoError == QNetworkReply::NoError) { + QJsonObject json = QJsonDocument::fromJson(reply->readAll()).object(); + QMap info; + for (auto it = json.begin();it != json.end();it ++) { + info[it.key()] = it.value().toString(); + } + m_instanceInfo = info; + emit instanceInfomationChanged(); + } + manager->deleteLater(); + }); + + m_timelineMap.clear(); + m_timelineMap["home"] = QUrl(instance().url() + SAORI_MASTODON_APIPATH_TIMELINE + "/home"); + m_timelineMap["local"] = QUrl(instance().url() + SAORI_MASTODON_APIPATH_TIMELINE + "/local"); + m_timelineMap["public"] = QUrl(instance().url() + SAORI_MASTODON_APIPATH_TIMELINE + "/public"); + m_timelineMap["notifications"] = QUrl(instance().url() + SAORI_MASTODON_APIPATH_TIMELINE + "/notifications"); + return; +} + +const QString Saoridon::instanceInfo(const QString key) +{ + return m_instanceInfo[key]; +} + +const QUrl Saoridon::timelineUrl(const QString timeline) +{ + return m_timelineMap[timeline]; +} + diff --git a/saoridon.h b/saoridon.h new file mode 100644 index 0000000..6b23229 --- /dev/null +++ b/saoridon.h @@ -0,0 +1,74 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#ifndef SAORIDON_H +#define SAORIDON_H + +#include +#include +#include + +class Saoridon : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUrl instance READ instance WRITE setInstance NOTIFY instanceChanged) + Q_PROPERTY(QString clientId READ clientId WRITE setClientId NOTIFY clientIdChanged) + Q_PROPERTY(QString clientSecret READ clientSecret WRITE setClientSecret NOTIFY clientSecretChanged) + +public: + Saoridon(QUrl instanceUrl,QObject *parent = nullptr); + const QUrl instance(); + void setInstance(const QUrl instanceUrl); + const QString clientId(); + void setClientId(const QString id); + const QString clientSecret(); + void setClientSecret(const QString secret); + bool clientRedistration(); + const QUrl getAuthorizedUrl(); + const QString getAccessToken(const QString code); + const QString instanceInfo(const QString key); + const QUrl timelineUrl(const QString timeline); + +protected: + void getInstanceInfomation(); + +protected: + QUrl m_instance; + QString m_clientId; + QString m_clientSecret; + QMap m_instanceInfo; + QMap m_timelineMap; + +signals: + void instanceChanged(QUrl); + void clientIdChanged(QString); + void clientSecretChanged(QString); + void instanceInfomationChanged(); + +public slots: +}; + +#endif // SAORIDON_H diff --git a/saoriview.cpp b/saoriview.cpp new file mode 100644 index 0000000..9aa6d06 --- /dev/null +++ b/saoriview.cpp @@ -0,0 +1,60 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#include "saoriview.h" +#include "ui_saoriview.h" +#include + +QList SaoriView::m_viewList; + +SaoriView::SaoriView(const QString view, const QString account, QWidget *parent) : + QWidget(parent), + ui(new Ui::SaoriView) +{ + ui->setupUi(this); + m_viewname = view; + m_account = account; + m_viewList.append(this); +} + +SaoriView::~SaoriView() +{ + delete ui; + m_viewList.removeOne(this); +} + +SaoriView *SaoriView::findView(const QString view, const QString account) +{ + for(auto v:m_viewList) { + if ((v->m_viewname == view) && (v->m_account == account)) return v; + } + return nullptr; +} + +void SaoriView::recived(QMap result) +{ + qDebug() << result; +} diff --git a/saoriview.h b/saoriview.h new file mode 100644 index 0000000..2f793be --- /dev/null +++ b/saoriview.h @@ -0,0 +1,58 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#ifndef SAORIVIEW_H +#define SAORIVIEW_H + +#include +#include + +namespace Ui { +class SaoriView; +} + +class SaoriView : public QWidget +{ + Q_OBJECT + +public: + explicit SaoriView(const QString view,const QString account,QWidget *parent = 0); + ~SaoriView(); + static SaoriView* findView(const QString view,const QString account); + +protected: + QString m_viewname; + QString m_account; + static QList m_viewList; + +public slots: + void recived(QMap result); + +private: + Ui::SaoriView *ui; +}; + +#endif // SAORIVIEW_H diff --git a/saoriview.ui b/saoriview.ui new file mode 100644 index 0000000..e4b2987 --- /dev/null +++ b/saoriview.ui @@ -0,0 +1,142 @@ + + + SaoriView + + + + 0 + 0 + 327 + 368 + + + + Form + + + + + + true + + + + + 0 + 0 + 307 + 316 + + + + + + + + + + 0 + + + + + Pin + + + + :/icons/ionicons/pin.svg:/icons/ionicons/pin.svg + + + true + + + + + + + Notify + + + + :/icons/ionicons/alert.svg:/icons/ionicons/alert.svg + + + true + + + + + + + Auto reload + + + + :/icons/ionicons/loop.svg:/icons/ionicons/loop.svg + + + true + + + + + + + Newest + + + + :/icons/ionicons/arrow-up-c.svg:/icons/ionicons/arrow-up-c.svg + + + + + + + Reload + + + + :/icons/ionicons/refresh.svg:/icons/ionicons/refresh.svg + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Toot + + + + :/icons/ionicons/chatbox.svg:/icons/ionicons/chatbox.svg + + + + + + + + + + + + diff --git a/saoriwindow.cpp b/saoriwindow.cpp new file mode 100644 index 0000000..df44ea7 --- /dev/null +++ b/saoriwindow.cpp @@ -0,0 +1,130 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#include +#include "saoriwindow.h" +#include "ui_saoriwindow.h" +#include "saoriapplication.h" +#include "saoriaddaccountdialog.h" +#include "saoriview.h" + +SaoriWindow::SaoriWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::SaoriWindow) +{ + ui->setupUi(this); + connect(ui->actionAdd_Account,&QAction::triggered,this,&SaoriWindow::openAccountDialog); + updateTimelineList(); +} + +SaoriWindow::~SaoriWindow() +{ + delete ui; +} + +void SaoriWindow::openView(const QStringList viewName) +{ + if (auto view = SaoriView::findView(viewName.at(1),viewName.at(0))) { + ui->mdiArea->setActiveSubWindow(qobject_cast(view->parent())); + return; + } + QString title = viewName.at(1) + ":" + viewName.at(0); + auto view = new SaoriView(viewName.at(1),viewName.at(0)); + auto sub = ui->mdiArea->addSubWindow(view); + sub->setWindowTitle(title); + sub->show(); +} + + + +void SaoriWindow::openAccountDialog() +{ + auto dialog = new SaoriAddAccountDialog(this); + if (dialog->exec() == QDialog::Accepted) { + dialog->m_account->setParent(QApplication::instance()); + SaoriApplication::getAccountList()->append(dialog->m_account); + } + delete dialog; +} + +void SaoriWindow::updateTimelineList() +{ + ui->timelineTree->clear(); + auto *accountItem = new QTreeWidgetItem(ui->timelineTree,QStringList() << tr("Accounts")); + accountItem->setIcon(0,QIcon(":/icons/ionicons/person-stalker.svg")); + for (int i = 0;i < SaoriApplication::getAccountList()->count();i ++) { + auto *item = new QTreeWidgetItem(accountItem,QStringList() << SaoriApplication::getAccountList()->at(i)->name()); + item->setIcon(0,QIcon(":/icons/ionicons/person.svg")); + accountItem->addChild(item); + for (auto tl:SaoriApplication::getAccountList()->at(i)->timelineList()) { + // trick for translation. + QStringList trtl; + QString tlText,icon; + trtl << "home" << "local" << "public" << "notifications"; + switch (trtl.indexOf(tl)) { + case 0: + tlText = tr("home"); + icon = ":/icons/ionicons/chatbubbles.svg"; + break; + case 1: + tlText = tr("local"); + icon = ":/icons/ionicons/chatbubble.svg"; + break; + case 2: + tlText = tr("public"); + icon = ":/icons/ionicons/earth.svg"; + break; + case 3: + tlText = tr("notifications"); + icon = ":/icons/ionicons/alert.svg"; + break; + default: + tlText = tl; + break; + } + auto tlItem = new QTreeWidgetItem(item,QStringList() << tlText + << SaoriApplication::getAccountList()->at(i)->name() + << tl); + if (!icon.isEmpty()) tlItem->setIcon(0,QIcon(icon)); + item->addChild(tlItem); + } + } + auto *instanceItem = new QTreeWidgetItem(ui->timelineTree,QStringList() << tr("Instances")); + for (int i = 0;i < SaoriApplication::getInstanceList()->count();i ++) { + auto *item = new QTreeWidgetItem(instanceItem,QStringList() << SaoriApplication::getInstanceList()->at(i)->instance().toString()); + instanceItem->addChild(item); + item->addChild(new QTreeWidgetItem(item,QStringList() << tr("Infomation"))); + } +} + +void SaoriWindow::on_timelineTree_itemDoubleClicked(QTreeWidgetItem *item, int) +{ + auto account = SaoriApplication::findAccount(item->text(1)); + if (account) { + qDebug() << account->instance()->timelineUrl(item->text(2)); + openView(QStringList() << item->text(1) << item->text(2)); + } +} diff --git a/saoriwindow.h b/saoriwindow.h new file mode 100644 index 0000000..58587ea --- /dev/null +++ b/saoriwindow.h @@ -0,0 +1,61 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#ifndef SAORIWINDOW_H +#define SAORIWINDOW_H + +#include +#include + +namespace Ui { +class SaoriWindow; +} + +class SaoriWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit SaoriWindow(QWidget *parent = 0); + ~SaoriWindow(); + +protected: + void openView(const QStringList viewName); + +protected slots: + void openAccountDialog(); + void updateTimelineList(); + +protected: + +private slots: + void on_timelineTree_itemDoubleClicked(QTreeWidgetItem *item, int); + +private: + Ui::SaoriWindow *ui; +}; + +#endif // SAORIWINDOW_H diff --git a/saoriwindow.ui b/saoriwindow.ui new file mode 100644 index 0000000..dff0541 --- /dev/null +++ b/saoriwindow.ui @@ -0,0 +1,247 @@ + + + SaoriWindow + + + + 0 + 0 + 768 + 628 + + + + Saori + + + false + + + QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks + + + + + + + QMdiArea::SubWindowView + + + false + + + true + + + QTabWidget::Rounded + + + QTabWidget::North + + + + + + + + + 0 + 0 + 768 + 22 + + + + true + + + + &File + + + + + + &View + + + + + + + + &Edit + + + + + + + + &Help + + + + + + + + + + TopToolBarArea + + + false + + + + + + true + + + + 0 + 0 + + + + QDockWidget::NoDockWidgetFeatures + + + Qt::LeftDockWidgetArea + + + Timeline &list + + + 1 + + + + false + + + + + + + 0 + 0 + + + + Auto reload Interval (minutes) + + + + + + + + + + Qt::DefaultContextMenu + + + + List + + + + + Account + + + + + Instance + + + + + + + + + + &Quit + + + + + true + + + true + + + Show/Hide Timeline &List + + + + + &Open Timeline + + + + + &Add Account + + + + + &Remove Account + + + + + true + + + &TabbedView mode + + + + + T&iled + + + + + + + + actionShow_Hide_Timeline_List + triggered(bool) + dockWidget + setVisible(bool) + + + -1 + -1 + + + 136 + 338 + + + + + actionTiled + triggered() + mdiArea + tileSubWindows() + + + -1 + -1 + + + 521 + 322 + + + + +