2#include <score/model/Skin.hpp>
3#include <score/widgets/Pixmap.hpp>
5#include <core/view/QRecentFilesMenu.h>
8#include <QDesktopServices>
11#include <QNetworkAccessManager>
12#include <QNetworkReply>
13#include <QNetworkRequest>
20#include <score_git_info.hpp>
29template <
typename OnSuccess,
typename OnError>
30class HTTPGet final :
public QNetworkAccessManager
33 explicit HTTPGet(QUrl url, OnSuccess on_success, OnError on_error) noexcept
34 : m_callback{std::move(on_success)}
35 , m_error{std::move(on_error)}
37 connect(
this, &QNetworkAccessManager::finished,
this, [
this](QNetworkReply* reply) {
40 qDebug() << reply->errorString();
45 m_callback(reply->readAll());
52 QNetworkRequest req{std::move(url)};
53 req.setRawHeader(
"User-Agent",
"curl/7.35.0");
55 req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute,
true);
57 QNetworkRequest::RedirectPolicyAttribute,
58 QNetworkRequest::UserVerifiedRedirectPolicy);
59 req.setAttribute(QNetworkRequest::Http2AllowedAttribute,
true);
61 auto reply = get(req);
62 connect(reply, &QNetworkReply::redirected, reply, &QNetworkReply::redirectAllowed);
77 const QFont& font,
const QString& text,
const QString url, QWidget* parent = 0);
79 void setOpenExternalLink(
bool val) { m_openExternalLink = val; }
80 void setPixmaps(
const QPixmap& pixmap,
const QPixmap& pixmapOn);
82 void disableInteractivity();
83 void setActiveColor(
const QColor& c);
84 void setInactiveColor(
const QColor& c);
85 void setTextOption(QTextOption opt) { m_textOption = opt; }
87 void labelPressed(
const QString& file) W_SIGNAL(labelPressed, file)
89 QRectF textBoundingBox(
double width)
const noexcept;
92 void paintEvent(QPaintEvent* event)
override;
93 void enterEvent(QEnterEvent* event)
override;
94 void leaveEvent(QEvent* event)
override;
95 void mousePressEvent(QMouseEvent* event)
override;
102 bool m_openExternalLink{};
105 QPixmap m_currentPixmap;
109 bool m_interactive{};
110 QColor m_currentColor;
111 QColor m_activeColor;
112 QColor m_inactiveColor;
114 QTextOption m_textOption;
117InteractiveLabel::InteractiveLabel(
118 const QFont& font,
const QString& title,
const QString url, QWidget* parent)
123 , m_openExternalLink(false)
124 , m_drawPixmap(false)
125 , m_interactive(true)
127 auto& skin = score::Skin::instance();
128 m_inactiveColor = QColor{
"#d3d3d3"};
129 m_activeColor = QColor{
"#03C3DD"};
130 m_currentColor = m_inactiveColor;
132 setFixedSize(200, 34);
135void InteractiveLabel::setPixmaps(
const QPixmap& pixmap,
const QPixmap& pixmapOn)
139 m_pixmapOn = pixmapOn;
140 m_currentPixmap = m_pixmap;
143void InteractiveLabel::disableInteractivity()
145 m_interactive =
false;
149void InteractiveLabel::setActiveColor(
const QColor& c)
154void InteractiveLabel::setInactiveColor(
const QColor& c)
157 m_currentColor = m_inactiveColor;
160QRectF InteractiveLabel::textBoundingBox(
double width)
const noexcept
162 int leading = QFontMetrics{m_font}.leading();
164 lay.setText(m_title);
166 lay.setTextOption(m_textOption);
171 QTextLine line = lay.createLine();
175 line.setLineWidth(width);
177 line.setPosition(QPointF(0, height));
178 height += line.height();
181 return lay.boundingRect();
184void InteractiveLabel::paintEvent(QPaintEvent* event)
186 QPainter painter(
this);
188 painter.setRenderHint(QPainter::Antialiasing,
true);
189 painter.setRenderHint(QPainter::TextAntialiasing,
true);
190 painter.setRenderHint(QPainter::RenderHint::SmoothPixmapTransform);
191 painter.setPen(QPen{m_currentColor});
194 QRectF textRect = rect();
197 int size = m_currentPixmap.width() / qApp->devicePixelRatio();
200 if(m_textOption.alignment() == Qt::AlignRight)
203 lay.setText(m_title);
205 lay.setTextOption(m_textOption);
209 pixmapX = lay.boundingRect().width();
212 width() - pixmapX - m_currentPixmap.width() - 6,
213 (textRect.height() - size - 10) / 2, m_currentPixmap);
214 textRect.setX(textRect.x() + size + 6);
216 painter.setFont(m_font);
217 painter.drawText(textRect, m_title, m_textOption);
221void InteractiveLabel::enterEvent(QEnterEvent* event)
226 m_currentColor = m_activeColor;
227 m_font.setUnderline(
true);
228 m_currentPixmap = m_pixmapOn;
233void InteractiveLabel::leaveEvent(QEvent* event)
238 m_currentColor = m_inactiveColor;
239 m_font.setUnderline(
false);
240 m_currentPixmap = m_pixmap;
245void InteractiveLabel::mousePressEvent(QMouseEvent* event)
247 if(m_openExternalLink)
249 QDesktopServices::openUrl(QUrl(m_url));
260 StartScreen(
const QPointer<QRecentFilesMenu>& recentFiles, QWidget* parent = 0);
262 void openNewDocument() W_SIGNAL(openNewDocument)
263 void openFile(
const QString& file) W_SIGNAL(openFile, file)
264 void openFileDialog() W_SIGNAL(openFileDialog)
265 void loadCrashedSession() W_SIGNAL(loadCrashedSession)
266 void exitApp() W_SIGNAL(exitApp)
268 void addLoadCrashedSession();
271 void paintEvent(QPaintEvent* event)
override;
272 void keyPressEvent(QKeyEvent* event)
override;
275 QPixmap m_background;
285 const QString& n,
const QString& u,
const QString& p,
const QString& pOn)
294StartScreen::StartScreen(
const QPointer<QRecentFilesMenu>& recentFiles, QWidget* parent)
298#if defined(__APPLE__)
299 static constexpr double font_factor = 96. / 72.;
301 static constexpr double font_factor = 1.;
303 QFont f(
"Ubuntu", 14 * font_factor, QFont::Light);
304 f.setHintingPreference(QFont::HintingPreference::PreferFullHinting);
305 f.setStyleStrategy(QFont::PreferAntialias);
307 QFont titleFont(
"Montserrat", 14 * font_factor, QFont::DemiBold);
308 titleFont.setHintingPreference(QFont::HintingPreference::PreferFullHinting);
309 titleFont.setStyleStrategy(QFont::PreferAntialias);
311 this->setEnabled(
true);
312 setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
313 setWindowModality(Qt::ApplicationModal);
315 m_background = score::get_pixmap(
":/startscreen/startscreensplash.png");
317 if(QPainter painter; painter.begin(&m_background))
319 painter.setRenderHint(QPainter::Antialiasing,
true);
320 painter.setRenderHint(QPainter::TextAntialiasing,
true);
321 painter.setPen(QPen(QColor(
"#0092CF")));
325 painter.drawText(QPointF(217, 188), QCoreApplication::applicationVersion());
330 setFixedSize(m_background.size() / m_background.devicePixelRatioF());
334 auto m_getLastVersion =
new HTTPGet{
335 QUrl(
"https://ossia.io/score-last-version.txt"),
336 [
this, titleFont](
const QByteArray& data) {
337 auto version = QString::fromUtf8(data.simplified());
338 if(SCORE_TAG_NO_V < version)
341 = qApp->tr(
"New version %1 is available, click to update !").arg(version);
342 QString url =
"https://github.com/ossia/score/releases/latest/";
343 InteractiveLabel* label =
new InteractiveLabel{titleFont, text, url,
this};
345 score::get_pixmap(
":/icons/version_on.png"),
346 score::get_pixmap(
":/icons/version_off.png"));
347 label->setOpenExternalLink(
true);
348 label->setInactiveColor(QColor{
"#f6a019"});
349 label->setActiveColor(QColor{
"#f0f0f0"});
350 label->setFixedWidth(600);
351 label->move(280, 170);
361 auto label =
new InteractiveLabel{titleFont, qApp->tr(
"Recent files"),
"",
this};
362 label->setTextOption(QTextOption(Qt::AlignRight));
364 score::get_pixmap(
":/icons/recent_files.png"),
365 score::get_pixmap(
":/icons/recent_files.png"));
366 label->setInactiveColor(QColor{
"#f0f0f0"});
367 label->setActiveColor(QColor{
"#03C3DD"});
368 label->disableInteractivity();
369 label->move(label_x, label_y);
375 for(
const auto& action : recentFiles->actions())
378 =
new InteractiveLabel{f, action->text(), action->data().toString(),
this};
379 fileLabel->setTextOption(QTextOption(Qt::AlignRight));
381 fileLabel, &score::InteractiveLabel::labelPressed,
this,
382 &score::StartScreen::openFile);
384 auto textHeight = std::max(25, (
int)fileLabel->textBoundingBox(200).height() + 7);
385 fileLabel->setFixedSize(200, textHeight);
386 fileLabel->move(label_x, label_y);
387 label_y += textHeight + 1;
393 =
new InteractiveLabel{titleFont, qApp->tr(
"Restore last session"),
"",
this};
394 m_crashLabel->setTextOption(QTextOption(Qt::AlignRight));
395 m_crashLabel->setPixmaps(
396 score::get_pixmap(
":/icons/reload_crash_off.png"),
397 score::get_pixmap(
":/icons/reload_crash_on.png"));
398 m_crashLabel->move(label_x - 100, label_y);
399 m_crashLabel->setFixedWidth(300);
400 m_crashLabel->setInactiveColor(QColor{
"#f0f0f0"});
401 m_crashLabel->setActiveColor(QColor{
"#f6a019"});
402 m_crashLabel->setDisabled(
true);
403 m_crashLabel->hide();
405 m_crashLabel, &score::InteractiveLabel::labelPressed,
this,
406 &score::StartScreen::loadCrashedSession);
411 InteractiveLabel* label =
new InteractiveLabel{titleFont, qApp->tr(
"New"),
"",
this};
413 score::get_pixmap(
":/icons/new_file_off.png"),
414 score::get_pixmap(
":/icons/new_file_on.png"));
416 label, &score::InteractiveLabel::labelPressed,
this,
417 &score::StartScreen::openNewDocument);
418 label->move(label_x, label_y);
422 InteractiveLabel* label
423 =
new InteractiveLabel{titleFont, qApp->tr(
"Load"),
"",
this};
425 score::get_pixmap(
":/icons/load_off.png"),
426 score::get_pixmap(
":/icons/load_on.png"));
428 label, &score::InteractiveLabel::labelPressed,
this,
429 &score::StartScreen::openFileDialog);
430 label->move(label_x, label_y);
435 auto library_path = settings.value(
"Library/RootPath").toString();
436 InteractiveLabel* label =
new InteractiveLabel{
437 titleFont, qApp->tr(
"Examples"),
"https://github.com/ossia/score-examples",
this};
439 score::get_pixmap(
":/icons/load_examples_off.png"),
440 score::get_pixmap(
":/icons/load_examples_on.png"));
441 label->setOpenExternalLink(
true);
442 label->move(label_x, label_y);
448 std::array<score::StartScreenLink, 4> menus
449 = {{{qApp->tr(
"Tutorials"),
450 "https://www.youtube.com/"
451 "watch?v=R-3d8K6gQkw&list=PLIHLSiZpIa6YoY1_aW1yetDgZ7tZcxfEC&index=1",
452 ":/icons/tutorials_off.png",
":/icons/tutorials_on.png"},
453 {qApp->tr(
"Contribute"),
"https://opencollective.com/ossia/contribute",
454 ":/icons/contribute_off.png",
":/icons/contribute_on.png"},
455 {qApp->tr(
"Forum"),
"http://forum.ossia.io/",
":/icons/forum_off.png",
456 ":/icons/forum_on.png"},
457 {qApp->tr(
"Chat"),
"https://gitter.im/ossia/score",
":/icons/chat_off.png",
458 ":/icons/chat_on.png"}}};
459 for(
const auto& m : menus)
461 InteractiveLabel* menu_url =
new InteractiveLabel{titleFont, m.name, m.url,
this};
462 menu_url->setOpenExternalLink(
true);
463 menu_url->setPixmaps(score::get_pixmap(m.pixmap), score::get_pixmap(m.pixmapOn));
464 menu_url->move(label_x, label_y);
471 InteractiveLabel* label
472 =
new InteractiveLabel{titleFont, qApp->tr(
"Exit"),
"",
this};
474 score::get_pixmap(
":/icons/exit_off.png"),
475 score::get_pixmap(
":/icons/exit_on.png"));
477 label, &score::InteractiveLabel::labelPressed,
this,
478 &score::StartScreen::exitApp);
479 label->move(label_x, label_y);
483void StartScreen::addLoadCrashedSession()
485 m_crashLabel->show();
486 m_crashLabel->setEnabled(
true);
490void StartScreen::paintEvent(QPaintEvent* event)
492 QPainter painter(
this);
493 painter.setRenderHint(QPainter::RenderHint::SmoothPixmapTransform);
494 painter.drawPixmap(0, 0, m_background);
497void StartScreen::keyPressEvent(QKeyEvent* event)
499 if(event->key() == Qt::Key_Escape)
501 this->openNewDocument();
503 return QWidget::keyPressEvent(event);
Definition StartScreen.hpp:72
Definition StartScreen.hpp:257
Base toolkit upon which the software is built.
Definition Application.cpp:90
void setCursor(Qt::CursorShape c)
setCursor sets the cursor safely.
Definition ClearLayout.cpp:8
Definition StartScreen.hpp:279