void ArtLoader::TempArtLoaded(quint64 id, const QImage& image) {
  if (id != id_)
    return;
  id_ = 0;

  QString uri;
  QString thumbnail_uri;
  QImage thumbnail;

  if (!image.isNull()) {
    temp_art_.reset(new QTemporaryFile(temp_file_pattern_));
    temp_art_->open();
    image.save(temp_art_->fileName(), "JPEG");

    // Scale the image down to make a thumbnail.  It's a bit crap doing it here
    // since it's the GUI thread, but the alternative is hard.
    temp_art_thumbnail_.reset(new QTemporaryFile(temp_file_pattern_));
    temp_art_thumbnail_->open();
    thumbnail = image.scaledToHeight(120, Qt::SmoothTransformation);
    thumbnail.save(temp_art_thumbnail_->fileName(), "JPEG");

    uri = "file://" + temp_art_->fileName();
    thumbnail_uri = "file://" + temp_art_thumbnail_->fileName();
  }

  emit ArtLoaded(last_song_, uri, image);
  emit ThumbnailLoaded(last_song_, thumbnail_uri, thumbnail);
}
void NowPlayingWidget::SetApplication(Application* app) {
  app_ = app;

  album_cover_choice_controller_->SetApplication(app_);
  connect(app_->current_art_loader(), SIGNAL(ArtLoaded(Song, QString, QImage)),
          SLOT(AlbumArtLoaded(Song, QString, QImage)));
}
int GlobalSearch::LoadArtAsync(const SearchProvider::Result& result) {
  const int id = next_id_++;

  pending_art_searches_[id] = result.pixmap_cache_key_;

  if (providers_.contains(result.provider_) &&
      !is_provider_usable(result.provider_)) {
    emit ArtLoaded(id, QPixmap());
    return id;
  }

  if (result.provider_->art_is_in_song_metadata()) {
    quint64 loader_id = app_->album_cover_loader()->LoadImageAsync(
        cover_loader_options_, result.metadata_);
    cover_loader_tasks_[loader_id] = id;
  } else if (providers_.contains(result.provider_) &&
             result.provider_->wants_serialised_art()) {
    QueuedArt request;
    request.id_ = id;
    request.result_ = result;

    QList<QueuedArt>* queued_art = &providers_[result.provider_].queued_art_;

    queued_art->append(request);

    if (queued_art->count() == 1) {
      TakeNextQueuedArt(result.provider_);
    }
  } else {
    result.provider_->LoadArtAsync(id, result);
  }

  return id;
}
void SoundCloudSearchProvider::AlbumArtLoaded(quint64 id, const QImage& image) {
  if (!cover_loader_tasks_.contains(id)) {
    return;
  }
  int original_id = cover_loader_tasks_.take(id);
  emit ArtLoaded(original_id, image);
}
Beispiel #5
0
EditTagDialog::EditTagDialog(Application* app, QWidget* parent)
  : QDialog(parent),
    ui_(new Ui_EditTagDialog),
    app_(app),
    album_cover_choice_controller_(new AlbumCoverChoiceController(this)),
    loading_(false),
    ignore_edits_(false),
    tag_fetcher_(new TagFetcher(this)),
    cover_art_id_(0),
    cover_art_is_set_(false),
    results_dialog_(new TrackSelectionDialog(this))
{
  cover_options_.default_output_image_ =
      AlbumCoverLoader::ScaleAndPad(cover_options_, QImage(":nocover.png"));

  connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64,QImage,QImage)),
          SLOT(ArtLoaded(quint64,QImage,QImage)));

  connect(tag_fetcher_, SIGNAL(ResultAvailable(Song, SongList)),
          results_dialog_, SLOT(FetchTagFinished(Song, SongList)),
          Qt::QueuedConnection);
  connect(tag_fetcher_, SIGNAL(Progress(Song,QString)),
          results_dialog_, SLOT(FetchTagProgress(Song,QString)));
  connect(results_dialog_, SIGNAL(SongChosen(Song, Song)),
          SLOT(FetchTagSongChosen(Song, Song)));
  connect(results_dialog_, SIGNAL(finished(int)), tag_fetcher_, SLOT(Cancel()));

  album_cover_choice_controller_->SetApplication(app_);

  ui_->setupUi(this);
  ui_->splitter->setSizes(QList<int>() << 200 << width() - 200);
  ui_->loading_label->hide();

  // An editable field is one that has a label as a buddy.  The label is
  // important because it gets turned bold when the field is changed.
  foreach (QLabel* label, findChildren<QLabel*>()) {
    QWidget* widget = label->buddy();
    if (widget) {
      // Store information about the field
      fields_ << FieldData(label, widget, widget->objectName());

      // Connect the Reset signal
      if (dynamic_cast<ExtendedEditor*>(widget)) {
        connect(widget, SIGNAL(Reset()), SLOT(ResetField()));
      }

      // Connect the edited signal
      if (qobject_cast<QLineEdit*>(widget)) {
        connect(widget, SIGNAL(textChanged(QString)), SLOT(FieldValueEdited()));
      } else if (qobject_cast<QPlainTextEdit*>(widget)) {
        connect(widget, SIGNAL(textChanged()), SLOT(FieldValueEdited()));
      } else if (qobject_cast<QSpinBox*>(widget)) {
        connect(widget, SIGNAL(valueChanged(int)), SLOT(FieldValueEdited()));
      }
    }
  }
Beispiel #6
0
void SpotifySearchProvider::ArtLoadedSlot(const QString& id, const QImage& image) {
  QMap<QString, int>::iterator it = pending_art_.find(id);
  if (it == pending_art_.end())
    return;

  const int orig_id = it.value();
  pending_art_.erase(it);

  emit ArtLoaded(orig_id, ScaleAndPad(image));
}
Beispiel #7
0
void SpotifySearchProvider::LoadArtAsync(int id, const Result& result) {
  SpotifyServer* s = server();
  if (!s) {
    emit ArtLoaded(id, QImage());
    return;
  }

  QString image_id = QUrl(result.metadata_.art_automatic()).path();
  if (image_id.startsWith('/'))
    image_id.remove(0, 1);

  pending_art_[image_id] = id;
  s->LoadImage(image_id);
}
void GlobalSearch::HandleLoadedArt(int id, const QImage& image,
                                   SearchProvider* provider) {
  const QString key = pending_art_searches_.take(id);

  QPixmap pixmap = QPixmap::fromImage(image);
  pixmap_cache_.insert(key, pixmap);

  emit ArtLoaded(id, pixmap);

  if (provider && providers_.contains(provider) &&
      !providers_[provider].queued_art_.isEmpty()) {
    providers_[provider].queued_art_.removeFirst();
    TakeNextQueuedArt(provider);
  }
}
void UrlSearchProvider::LoadArtAsync(int id, const Result&) {
  emit ArtLoaded(id, image_);
}
Beispiel #10
0
EditTagDialog::EditTagDialog(Application* app, QWidget* parent)
    : QDialog(parent),
      ui_(new Ui_EditTagDialog),
      app_(app),
      album_cover_choice_controller_(new AlbumCoverChoiceController(this)),
      loading_(false),
      ignore_edits_(false),
      tag_fetcher_(new TagFetcher(this)),
      cover_art_id_(0),
      cover_art_is_set_(false),
      results_dialog_(new TrackSelectionDialog(this)) {
  cover_options_.default_output_image_ =
      AlbumCoverLoader::ScaleAndPad(cover_options_, QImage(":nocover.png"));

  connect(app_->album_cover_loader(),
          SIGNAL(ImageLoaded(quint64, QImage, QImage)),
          SLOT(ArtLoaded(quint64, QImage, QImage)));

  connect(tag_fetcher_, SIGNAL(ResultAvailable(Song, SongList)),
          results_dialog_, SLOT(FetchTagFinished(Song, SongList)),
          Qt::QueuedConnection);
  connect(tag_fetcher_, SIGNAL(Progress(Song, QString)), results_dialog_,
          SLOT(FetchTagProgress(Song, QString)));
  connect(results_dialog_, SIGNAL(SongChosen(Song, Song)),
          SLOT(FetchTagSongChosen(Song, Song)));
  connect(results_dialog_, SIGNAL(finished(int)), tag_fetcher_, SLOT(Cancel()));

  album_cover_choice_controller_->SetApplication(app_);

  ui_->setupUi(this);
  ui_->splitter->setSizes(QList<int>() << 200 << width() - 200);
  ui_->loading_label->hide();

  // An editable field is one that has a label as a buddy.  The label is
  // important because it gets turned bold when the field is changed.
  for (QLabel* label : findChildren<QLabel*>()) {
    QWidget* widget = label->buddy();
    if (widget) {
      // Store information about the field
      fields_ << FieldData(label, widget, widget->objectName());

      // Connect the Reset signal
      if (dynamic_cast<ExtendedEditor*>(widget)) {
        connect(widget, SIGNAL(Reset()), SLOT(ResetField()));
      }

      // Connect the edited signal
      if (qobject_cast<QLineEdit*>(widget)) {
        connect(widget, SIGNAL(textChanged(QString)), SLOT(FieldValueEdited()));
      } else if (qobject_cast<QPlainTextEdit*>(widget)) {
        connect(widget, SIGNAL(textChanged()), SLOT(FieldValueEdited()));
      } else if (qobject_cast<QSpinBox*>(widget)) {
        connect(widget, SIGNAL(valueChanged(int)), SLOT(FieldValueEdited()));
      }
    }
  }

  // Set the colour of all the labels on the summary page
  const bool light = palette().color(QPalette::Base).value() > 128;
  const QColor color = palette().color(QPalette::Dark);
  QPalette summary_label_palette(palette());
  summary_label_palette.setColor(
      QPalette::WindowText, light ? color.darker(150) : color.lighter(125));

  for (QLabel* label : ui_->summary_tab->findChildren<QLabel*>()) {
    if (label->property("field_label").toBool()) {
      label->setPalette(summary_label_palette);
    }
  }

  // Pretend the summary text is just a label
  ui_->summary->setMaximumHeight(ui_->art->height() -
                                 ui_->summary_art_button->height() - 4);

  connect(ui_->song_list->selectionModel(),
          SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
          SLOT(SelectionChanged()));
  connect(ui_->button_box, SIGNAL(clicked(QAbstractButton*)),
          SLOT(ButtonClicked(QAbstractButton*)));
  connect(ui_->rating, SIGNAL(RatingChanged(float)), SLOT(SongRated(float)));
  connect(ui_->playcount_reset, SIGNAL(clicked()), SLOT(ResetPlayCounts()));
  connect(ui_->fetch_tag, SIGNAL(clicked()), SLOT(FetchTag()));

  // Set up the album cover menu
  cover_menu_ = new QMenu(this);

  QList<QAction*> actions = album_cover_choice_controller_->GetAllActions();

  connect(album_cover_choice_controller_->cover_from_file_action(),
          SIGNAL(triggered()), this, SLOT(LoadCoverFromFile()));
  connect(album_cover_choice_controller_->cover_to_file_action(),
          SIGNAL(triggered()), this, SLOT(SaveCoverToFile()));
  connect(album_cover_choice_controller_->cover_from_url_action(),
          SIGNAL(triggered()), this, SLOT(LoadCoverFromURL()));
  connect(album_cover_choice_controller_->search_for_cover_action(),
          SIGNAL(triggered()), this, SLOT(SearchForCover()));
  connect(album_cover_choice_controller_->unset_cover_action(),
          SIGNAL(triggered()), this, SLOT(UnsetCover()));
  connect(album_cover_choice_controller_->show_cover_action(),
          SIGNAL(triggered()), this, SLOT(ShowCover()));

  cover_menu_->addActions(actions);

  ui_->summary_art_button->setMenu(cover_menu_);

  ui_->art->installEventFilter(this);
  ui_->art->setAcceptDrops(true);

  // Add the next/previous buttons
  previous_button_ =
      new QPushButton(IconLoader::Load("go-previous"), tr("Previous"), this);
  next_button_ = new QPushButton(IconLoader::Load("go-next"), tr("Next"), this);
  ui_->button_box->addButton(previous_button_, QDialogButtonBox::ResetRole);
  ui_->button_box->addButton(next_button_, QDialogButtonBox::ResetRole);

  connect(previous_button_, SIGNAL(clicked()), SLOT(PreviousSong()));
  connect(next_button_, SIGNAL(clicked()), SLOT(NextSong()));

  // Set some shortcuts for the buttons
  new QShortcut(QKeySequence::Back, previous_button_, SLOT(click()));
  new QShortcut(QKeySequence::Forward, next_button_, SLOT(click()));
  new QShortcut(QKeySequence::MoveToPreviousPage, previous_button_,
                SLOT(click()));
  new QShortcut(QKeySequence::MoveToNextPage, next_button_, SLOT(click()));

  // Show the shortcuts as tooltips
  previous_button_->setToolTip(QString("%1 (%2 / %3)").arg(
      previous_button_->text(),
      QKeySequence(QKeySequence::Back).toString(QKeySequence::NativeText),
      QKeySequence(QKeySequence::MoveToPreviousPage)
          .toString(QKeySequence::NativeText)));
  next_button_->setToolTip(QString("%1 (%2 / %3)").arg(
      next_button_->text(),
      QKeySequence(QKeySequence::Forward).toString(QKeySequence::NativeText),
      QKeySequence(QKeySequence::MoveToNextPage)
          .toString(QKeySequence::NativeText)));

  new TagCompleter(app_->library_backend(), Playlist::Column_Artist,
                   ui_->artist);
  new TagCompleter(app_->library_backend(), Playlist::Column_Album, ui_->album);
  new TagCompleter(app_->library_backend(), Playlist::Column_AlbumArtist,
                   ui_->albumartist);
  new TagCompleter(app_->library_backend(), Playlist::Column_Genre, ui_->genre);
  new TagCompleter(app_->library_backend(), Playlist::Column_Composer,
                   ui_->composer);
  new TagCompleter(app_->library_backend(), Playlist::Column_Performer,
                   ui_->performer);
  new TagCompleter(app_->library_backend(), Playlist::Column_Grouping,
                   ui_->grouping);
}
void SearchProvider::LoadArtAsync(int id, const Result& result) {
  emit ArtLoaded(id, QImage());
}
Beispiel #12
0
void LastFMSearchProvider::LoadArtAsync(int id, const Result& result) {
  // TODO: Maybe we should try to get user pictures for friends?

  emit ArtLoaded(id, icon_);
}
void SomaFMSearchProvider::LoadArtAsync(int id, const Result& result) {
  emit ArtLoaded(id, icon_);
}
void IntergalacticFMSearchProvider::LoadArtAsync(int id, const Result& result) {
  emit ArtLoaded(id, icon_);
}