2 #include <score/model/Skin.hpp>
3 #include <score/widgets/Pixmap.hpp>
5 #include <core/view/QRecentFilesMenu.h>
7 #include <QApplication>
8 #include <QDesktopServices>
11 #include <QNetworkAccessManager>
12 #include <QNetworkReply>
13 #include <QNetworkRequest>
18 #include <QTextLayout>
20 #include <score_git_info.hpp>
29 template <
typename OnSuccess,
typename OnError>
30 class 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;
117 InteractiveLabel::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);
135 void InteractiveLabel::setPixmaps(
const QPixmap& pixmap,
const QPixmap& pixmapOn)
139 m_pixmapOn = pixmapOn;
140 m_currentPixmap = m_pixmap;
143 void InteractiveLabel::disableInteractivity()
145 m_interactive =
false;
149 void InteractiveLabel::setActiveColor(
const QColor& c)
154 void InteractiveLabel::setInactiveColor(
const QColor& c)
157 m_currentColor = m_inactiveColor;
160 QRectF 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();
184 void InteractiveLabel::paintEvent(QPaintEvent* event)
186 QPainter painter(
this);
188 painter.setRenderHint(QPainter::Antialiasing,
true);
189 painter.setRenderHint(QPainter::TextAntialiasing,
true);
190 painter.setPen(QPen{m_currentColor});
193 QRectF textRect = rect();
196 int size = m_currentPixmap.width() / qApp->devicePixelRatio();
199 if(m_textOption.alignment() == Qt::AlignRight)
202 lay.setText(m_title);
204 lay.setTextOption(m_textOption);
208 pixmapX = lay.boundingRect().width();
211 width() - pixmapX - m_currentPixmap.width() - 6,
212 (textRect.height() - size - 10) / 2, m_currentPixmap);
213 textRect.setX(textRect.x() + size + 6);
215 painter.setFont(m_font);
216 painter.drawText(textRect, m_title, m_textOption);
220 void InteractiveLabel::enterEvent(QEnterEvent* event)
225 m_currentColor = m_activeColor;
226 m_font.setUnderline(
true);
227 m_currentPixmap = m_pixmapOn;
232 void InteractiveLabel::leaveEvent(QEvent* event)
237 m_currentColor = m_inactiveColor;
238 m_font.setUnderline(
false);
239 m_currentPixmap = m_pixmap;
244 void InteractiveLabel::mousePressEvent(QMouseEvent* event)
246 if(m_openExternalLink)
248 QDesktopServices::openUrl(QUrl(m_url));
259 StartScreen(
const QPointer<QRecentFilesMenu>& recentFiles, QWidget* parent = 0);
261 void openNewDocument() W_SIGNAL(openNewDocument)
262 void openFile(
const QString& file) W_SIGNAL(openFile, file)
263 void openFileDialog() W_SIGNAL(openFileDialog)
264 void loadCrashedSession() W_SIGNAL(loadCrashedSession)
265 void exitApp() W_SIGNAL(exitApp)
267 void addLoadCrashedSession();
270 void paintEvent(QPaintEvent* event)
override;
271 void keyPressEvent(QKeyEvent* event)
override;
274 QPixmap m_background;
284 const QString& n,
const QString& u,
const QString& p,
const QString& pOn)
293 StartScreen::StartScreen(
const QPointer<QRecentFilesMenu>& recentFiles, QWidget* parent)
297 #if defined(__APPLE__)
298 static constexpr
double font_factor = 96. / 72.;
300 static constexpr
double font_factor = 1.;
302 QFont f(
"Ubuntu", 14 * font_factor, QFont::Light);
303 f.setHintingPreference(QFont::HintingPreference::PreferFullHinting);
304 f.setStyleStrategy(QFont::PreferAntialias);
306 QFont titleFont(
"Montserrat", 14 * font_factor, QFont::DemiBold);
307 titleFont.setHintingPreference(QFont::HintingPreference::PreferFullHinting);
308 titleFont.setStyleStrategy(QFont::PreferAntialias);
310 this->setEnabled(
true);
311 setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
312 setWindowModality(Qt::ApplicationModal);
314 m_background = score::get_pixmap(
":/startscreen/startscreensplash.png");
316 if(QPainter painter; painter.begin(&m_background))
318 painter.setRenderHint(QPainter::Antialiasing,
true);
319 painter.setRenderHint(QPainter::TextAntialiasing,
true);
320 painter.setPen(QPen(QColor(
"#0092CF")));
324 painter.drawText(QPointF(217, 188), QCoreApplication::applicationVersion());
329 setFixedSize(m_background.size() / std::floor(qApp->devicePixelRatio()));
333 auto m_getLastVersion =
new HTTPGet{
334 QUrl(
"https://ossia.io/score-last-version.txt"),
335 [
this, titleFont](
const QByteArray& data) {
336 auto version = QString::fromUtf8(data.simplified());
337 if(SCORE_TAG_NO_V < version)
340 = qApp->tr(
"New version %1 is available, click to update !").arg(version);
341 QString url =
"https://github.com/ossia/score/releases/latest/";
342 InteractiveLabel* label =
new InteractiveLabel{titleFont, text, url,
this};
344 score::get_pixmap(
":/icons/version_on.png"),
345 score::get_pixmap(
":/icons/version_off.png"));
346 label->setOpenExternalLink(
true);
347 label->setInactiveColor(QColor{
"#f6a019"});
348 label->setActiveColor(QColor{
"#f0f0f0"});
349 label->setFixedWidth(600);
350 label->move(280, 170);
360 auto label =
new InteractiveLabel{titleFont, qApp->tr(
"Recent files"),
"",
this};
361 label->setTextOption(QTextOption(Qt::AlignRight));
363 score::get_pixmap(
":/icons/recent_files.png"),
364 score::get_pixmap(
":/icons/recent_files.png"));
365 label->setInactiveColor(QColor{
"#f0f0f0"});
366 label->setActiveColor(QColor{
"#03C3DD"});
367 label->disableInteractivity();
368 label->move(label_x, label_y);
374 for(
const auto& action : recentFiles->actions())
377 =
new InteractiveLabel{f, action->text(), action->data().toString(),
this};
378 fileLabel->setTextOption(QTextOption(Qt::AlignRight));
380 fileLabel, &score::InteractiveLabel::labelPressed,
this,
381 &score::StartScreen::openFile);
383 auto textHeight = std::max(25, (
int)fileLabel->textBoundingBox(200).height() + 7);
384 fileLabel->setFixedSize(200, textHeight);
385 fileLabel->move(label_x, label_y);
386 label_y += textHeight + 1;
392 =
new InteractiveLabel{titleFont, qApp->tr(
"Restore last session"),
"",
this};
393 m_crashLabel->setTextOption(QTextOption(Qt::AlignRight));
394 m_crashLabel->setPixmaps(
395 score::get_pixmap(
":/icons/reload_crash_off.png"),
396 score::get_pixmap(
":/icons/reload_crash_on.png"));
397 m_crashLabel->move(label_x - 100, label_y);
398 m_crashLabel->setFixedWidth(300);
399 m_crashLabel->setInactiveColor(QColor{
"#f0f0f0"});
400 m_crashLabel->setActiveColor(QColor{
"#f6a019"});
401 m_crashLabel->setDisabled(
true);
402 m_crashLabel->hide();
404 m_crashLabel, &score::InteractiveLabel::labelPressed,
this,
405 &score::StartScreen::loadCrashedSession);
410 InteractiveLabel* label =
new InteractiveLabel{titleFont, qApp->tr(
"New"),
"",
this};
412 score::get_pixmap(
":/icons/new_file_off.png"),
413 score::get_pixmap(
":/icons/new_file_on.png"));
415 label, &score::InteractiveLabel::labelPressed,
this,
416 &score::StartScreen::openNewDocument);
417 label->move(label_x, label_y);
421 InteractiveLabel* label
422 =
new InteractiveLabel{titleFont, qApp->tr(
"Load"),
"",
this};
424 score::get_pixmap(
":/icons/load_off.png"),
425 score::get_pixmap(
":/icons/load_on.png"));
427 label, &score::InteractiveLabel::labelPressed,
this,
428 &score::StartScreen::openFileDialog);
429 label->move(label_x, label_y);
434 auto library_path = settings.value(
"Library/RootPath").toString();
435 InteractiveLabel* label =
new InteractiveLabel{
436 titleFont, qApp->tr(
"Examples"),
"https://github.com/ossia/score-examples",
this};
438 score::get_pixmap(
":/icons/load_examples_off.png"),
439 score::get_pixmap(
":/icons/load_examples_on.png"));
440 label->setOpenExternalLink(
true);
441 label->move(label_x, label_y);
447 std::array<score::StartScreenLink, 4> menus
448 = {{{qApp->tr(
"Tutorials"),
449 "https://www.youtube.com/"
450 "watch?v=R-3d8K6gQkw&list=PLIHLSiZpIa6YoY1_aW1yetDgZ7tZcxfEC&index=1",
451 ":/icons/tutorials_off.png",
":/icons/tutorials_on.png"},
452 {qApp->tr(
"Contribute"),
"https://opencollective.com/ossia/contribute",
453 ":/icons/contribute_off.png",
":/icons/contribute_on.png"},
454 {qApp->tr(
"Forum"),
"http://forum.ossia.io/",
":/icons/forum_off.png",
455 ":/icons/forum_on.png"},
456 {qApp->tr(
"Chat"),
"https://gitter.im/ossia/score",
":/icons/chat_off.png",
457 ":/icons/chat_on.png"}}};
458 for(
const auto& m : menus)
460 InteractiveLabel* menu_url =
new InteractiveLabel{titleFont, m.name, m.url,
this};
461 menu_url->setOpenExternalLink(
true);
462 menu_url->setPixmaps(score::get_pixmap(m.pixmap), score::get_pixmap(m.pixmapOn));
463 menu_url->move(label_x, label_y);
470 InteractiveLabel* label
471 =
new InteractiveLabel{titleFont, qApp->tr(
"Exit"),
"",
this};
473 score::get_pixmap(
":/icons/exit_off.png"),
474 score::get_pixmap(
":/icons/exit_on.png"));
476 label, &score::InteractiveLabel::labelPressed,
this,
477 &score::StartScreen::exitApp);
478 label->move(label_x, label_y);
482 void StartScreen::addLoadCrashedSession()
484 m_crashLabel->show();
485 m_crashLabel->setEnabled(
true);
489 void StartScreen::paintEvent(QPaintEvent* event)
491 QPainter painter(
this);
492 painter.drawPixmap(0, 0, m_background);
495 void StartScreen::keyPressEvent(QKeyEvent* event)
497 if(event->key() == Qt::Key_Escape)
499 this->openNewDocument();
501 return QWidget::keyPressEvent(event);
Definition: StartScreen.hpp:72
Definition: StartScreen.hpp:256
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:278