Merge branch 'master' of https://github.com/clementine-player/Clementine
This commit is contained in:
commit
d14e272018
26
README.md
Normal file
26
README.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Clementine
|
||||||
|
==========
|
||||||
|
|
||||||
|
Clementine is a modern music player and library organizer for Windows, Linux and Mac OS X.
|
||||||
|
|
||||||
|
- Website: http://www.clementine-player.org/
|
||||||
|
- Github: https://github.com/clementine-player/Clementine
|
||||||
|
- Buildbot: http://buildbot.clementine-player.org/grid
|
||||||
|
- Latest developer builds: http://builds.clementine-player.org/
|
||||||
|
|
||||||
|
Compiling from source
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Get the code (if you haven't already):
|
||||||
|
|
||||||
|
git clone https://github.com/clementine-player/Clementine.git && cd Clementine
|
||||||
|
|
||||||
|
Compile and install:
|
||||||
|
|
||||||
|
cd bin
|
||||||
|
cmake ..
|
||||||
|
make -j8
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
See the Wiki for more instructions and a list of dependencies:
|
||||||
|
https://github.com/clementine-player/Clementine/wiki/Compiling-from-Source
|
@ -451,4 +451,12 @@ void EnableFullScreen(const QWidget& main_window) {
|
|||||||
[window setCollectionBehavior: kFullScreenPrimary];
|
[window setCollectionBehavior: kFullScreenPrimary];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float GetDevicePixelRatio(QWidget* widget) {
|
||||||
|
NSView* view = reinterpret_cast<NSView*>(widget->winId());
|
||||||
|
if ([[view window] respondsToSelector: @selector(backingScaleFactor)]) {
|
||||||
|
return [[view window] backingScaleFactor];
|
||||||
|
}
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mac
|
} // namespace mac
|
||||||
|
@ -29,5 +29,6 @@ namespace mac {
|
|||||||
|
|
||||||
QKeySequence KeySequenceFromNSEvent(NSEvent* event);
|
QKeySequence KeySequenceFromNSEvent(NSEvent* event);
|
||||||
void DumpDictionary(CFDictionaryRef dict);
|
void DumpDictionary(CFDictionaryRef dict);
|
||||||
|
float GetDevicePixelRatio(QWidget* widget);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -212,6 +212,10 @@ void LibraryFilterWidget::SetQueryMode(QueryOptions::QueryMode query_mode) {
|
|||||||
model_->SetFilterQueryMode(query_mode);
|
model_->SetFilterQueryMode(query_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LibraryFilterWidget::ShowInLibrary(const QString& search) {
|
||||||
|
ui_->filter->setText(search);
|
||||||
|
}
|
||||||
|
|
||||||
void LibraryFilterWidget::SetAgeFilterEnabled(bool enabled) {
|
void LibraryFilterWidget::SetAgeFilterEnabled(bool enabled) {
|
||||||
filter_age_menu_->setEnabled(enabled);
|
filter_age_menu_->setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ class LibraryFilterWidget : public QWidget {
|
|||||||
void SetDelayBehaviour(DelayBehaviour behaviour) { delay_behaviour_ = behaviour; }
|
void SetDelayBehaviour(DelayBehaviour behaviour) { delay_behaviour_ = behaviour; }
|
||||||
void SetAgeFilterEnabled(bool enabled);
|
void SetAgeFilterEnabled(bool enabled);
|
||||||
void SetGroupByEnabled(bool enabled);
|
void SetGroupByEnabled(bool enabled);
|
||||||
|
void ShowInLibrary(const QString& search);
|
||||||
|
|
||||||
QMenu* menu() const { return library_menu_; }
|
QMenu* menu() const { return library_menu_; }
|
||||||
void AddMenuAction(QAction* action);
|
void AddMenuAction(QAction* action);
|
||||||
|
@ -16,13 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "playlistdelegates.h"
|
#include "playlistdelegates.h"
|
||||||
#include "queue.h"
|
|
||||||
#include "core/logging.h"
|
|
||||||
#include "core/player.h"
|
|
||||||
#include "core/utilities.h"
|
|
||||||
#include "library/librarybackend.h"
|
|
||||||
#include "widgets/trackslider.h"
|
|
||||||
#include "ui/iconloader.h"
|
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@ -39,6 +32,18 @@
|
|||||||
#include <QWhatsThis>
|
#include <QWhatsThis>
|
||||||
#include <QtConcurrentRun>
|
#include <QtConcurrentRun>
|
||||||
|
|
||||||
|
#include "queue.h"
|
||||||
|
#include "core/logging.h"
|
||||||
|
#include "core/player.h"
|
||||||
|
#include "core/utilities.h"
|
||||||
|
#include "library/librarybackend.h"
|
||||||
|
#include "widgets/trackslider.h"
|
||||||
|
#include "ui/iconloader.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_DARWIN
|
||||||
|
#include "core/mac_utilities.h"
|
||||||
|
#endif // Q_OS_DARWIN
|
||||||
|
|
||||||
const int QueuedItemDelegate::kQueueBoxBorder = 1;
|
const int QueuedItemDelegate::kQueueBoxBorder = 1;
|
||||||
const int QueuedItemDelegate::kQueueBoxCornerRadius = 3;
|
const int QueuedItemDelegate::kQueueBoxCornerRadius = 3;
|
||||||
const int QueuedItemDelegate::kQueueBoxLength = 30;
|
const int QueuedItemDelegate::kQueueBoxLength = 30;
|
||||||
@ -492,8 +497,14 @@ void SongSourceDelegate::paint(
|
|||||||
const QUrl& url = index.data().toUrl();
|
const QUrl& url = index.data().toUrl();
|
||||||
QPixmap pixmap = LookupPixmap(url, option_copy.decorationSize);
|
QPixmap pixmap = LookupPixmap(url, option_copy.decorationSize);
|
||||||
|
|
||||||
|
float device_pixel_ratio = 1.0f;
|
||||||
|
#ifdef Q_OS_DARWIN
|
||||||
|
QWidget* parent_widget = reinterpret_cast<QWidget*>(parent());
|
||||||
|
device_pixel_ratio = mac::GetDevicePixelRatio(parent_widget);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Draw the pixmap in the middle of the rectangle
|
// Draw the pixmap in the middle of the rectangle
|
||||||
QRect draw_rect(QPoint(0, 0), option_copy.decorationSize);
|
QRect draw_rect(QPoint(0, 0), option_copy.decorationSize / device_pixel_ratio);
|
||||||
draw_rect.moveCenter(option_copy.rect.center());
|
draw_rect.moveCenter(option_copy.rect.center());
|
||||||
|
|
||||||
painter->drawPixmap(draw_rect, pixmap);
|
painter->drawPixmap(draw_rect, pixmap);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "transcoderoptionsdialog.h"
|
#include "transcoderoptionsdialog.h"
|
||||||
#include "ui_transcodedialog.h"
|
#include "ui_transcodedialog.h"
|
||||||
#include "ui_transcodelogdialog.h"
|
#include "ui_transcodelogdialog.h"
|
||||||
|
#include "ui/iconloader.h"
|
||||||
#include "ui/mainwindow.h"
|
#include "ui/mainwindow.h"
|
||||||
#include "widgets/fileview.h"
|
#include "widgets/fileview.h"
|
||||||
|
|
||||||
@ -35,6 +36,7 @@
|
|||||||
|
|
||||||
const char* TranscodeDialog::kSettingsGroup = "Transcoder";
|
const char* TranscodeDialog::kSettingsGroup = "Transcoder";
|
||||||
const int TranscodeDialog::kProgressInterval = 500;
|
const int TranscodeDialog::kProgressInterval = 500;
|
||||||
|
const int TranscodeDialog::kMaxDestinationItems = 10;
|
||||||
|
|
||||||
static bool ComparePresetsByName(const TranscoderPreset& left,
|
static bool ComparePresetsByName(const TranscoderPreset& left,
|
||||||
const TranscoderPreset& right) {
|
const TranscoderPreset& right) {
|
||||||
@ -103,6 +105,8 @@ TranscodeDialog::TranscodeDialog(QWidget *parent)
|
|||||||
connect(close_button_, SIGNAL(clicked()), SLOT(hide()));
|
connect(close_button_, SIGNAL(clicked()), SLOT(hide()));
|
||||||
connect(ui_->details, SIGNAL(clicked()), log_dialog_, SLOT(show()));
|
connect(ui_->details, SIGNAL(clicked()), log_dialog_, SLOT(show()));
|
||||||
connect(ui_->options, SIGNAL(clicked()), SLOT(Options()));
|
connect(ui_->options, SIGNAL(clicked()), SLOT(Options()));
|
||||||
|
connect(ui_->select, SIGNAL(clicked()), SLOT(AddDestination()));
|
||||||
|
|
||||||
|
|
||||||
connect(transcoder_, SIGNAL(JobComplete(QString,bool)), SLOT(JobComplete(QString,bool)));
|
connect(transcoder_, SIGNAL(JobComplete(QString,bool)), SLOT(JobComplete(QString,bool)));
|
||||||
connect(transcoder_, SIGNAL(LogLine(QString)), SLOT(LogLine(QString)));
|
connect(transcoder_, SIGNAL(LogLine(QString)), SLOT(LogLine(QString)));
|
||||||
@ -138,7 +142,8 @@ void TranscodeDialog::Start() {
|
|||||||
// Add jobs to the transcoder
|
// Add jobs to the transcoder
|
||||||
for (int i=0 ; i<file_model->rowCount() ; ++i) {
|
for (int i=0 ; i<file_model->rowCount() ; ++i) {
|
||||||
QString filename = file_model->index(i, 0).data(Qt::UserRole).toString();
|
QString filename = file_model->index(i, 0).data(Qt::UserRole).toString();
|
||||||
transcoder_->AddJob(filename, preset);
|
QString outfilename = GetOutputFileName(filename, preset);
|
||||||
|
transcoder_->AddJob(filename, preset, outfilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the progressbar
|
// Set up the progressbar
|
||||||
@ -265,3 +270,50 @@ void TranscodeDialog::Options() {
|
|||||||
dialog.exec();
|
dialog.exec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adds a folder to the destination box.
|
||||||
|
void TranscodeDialog::AddDestination() {
|
||||||
|
int index = ui_->destination->currentIndex();
|
||||||
|
QString initial_dir = (!ui_->destination->itemData(index).isNull() ?
|
||||||
|
ui_->destination->itemData(index).toString() :
|
||||||
|
QDir::homePath());
|
||||||
|
QString dir = QFileDialog::getExistingDirectory(
|
||||||
|
this, tr("Add folder"), initial_dir);
|
||||||
|
|
||||||
|
if (!dir.isEmpty()) {
|
||||||
|
// Keep only a finite number of items in the box.
|
||||||
|
while (ui_->destination->count() >= kMaxDestinationItems) {
|
||||||
|
ui_->destination->removeItem(1); // The oldest folder item.
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon icon = IconLoader::Load("folder");
|
||||||
|
QVariant data = QVariant::fromValue(dir);
|
||||||
|
// Do not insert duplicates.
|
||||||
|
int duplicate_index = ui_->destination->findData(data);
|
||||||
|
if (duplicate_index == -1) {
|
||||||
|
ui_->destination->addItem(icon, dir, data);
|
||||||
|
ui_->destination->setCurrentIndex(ui_->destination->count() - 1);
|
||||||
|
} else {
|
||||||
|
ui_->destination->setCurrentIndex(duplicate_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the rightmost non-empty part of 'path'.
|
||||||
|
QString TranscodeDialog::TrimPath(const QString& path) const {
|
||||||
|
return path.section('/', -1, -1, QString::SectionSkipEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TranscodeDialog::GetOutputFileName(const QString& input,
|
||||||
|
const TranscoderPreset &preset) const {
|
||||||
|
QString path = ui_->destination->itemData(
|
||||||
|
ui_->destination->currentIndex()).toString();
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
// Keep the original path.
|
||||||
|
return input.section('.', 0, -2) + '.' + preset.extension_;
|
||||||
|
} else {
|
||||||
|
QString file_name = TrimPath(input);
|
||||||
|
file_name = file_name.section('.', 0, -2);
|
||||||
|
return path + '/' + file_name + '.' + preset.extension_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -25,6 +25,8 @@ class Transcoder;
|
|||||||
class Ui_TranscodeDialog;
|
class Ui_TranscodeDialog;
|
||||||
class Ui_TranscodeLogDialog;
|
class Ui_TranscodeLogDialog;
|
||||||
|
|
||||||
|
struct TranscoderPreset;
|
||||||
|
|
||||||
class TranscodeDialog : public QDialog {
|
class TranscodeDialog : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -34,6 +36,7 @@ class TranscodeDialog : public QDialog {
|
|||||||
|
|
||||||
static const char* kSettingsGroup;
|
static const char* kSettingsGroup;
|
||||||
static const int kProgressInterval;
|
static const int kProgressInterval;
|
||||||
|
static const int kMaxDestinationItems;
|
||||||
|
|
||||||
void SetFilenames(const QStringList& filenames);
|
void SetFilenames(const QStringList& filenames);
|
||||||
|
|
||||||
@ -49,11 +52,15 @@ class TranscodeDialog : public QDialog {
|
|||||||
void LogLine(const QString& message);
|
void LogLine(const QString& message);
|
||||||
void AllJobsComplete();
|
void AllJobsComplete();
|
||||||
void Options();
|
void Options();
|
||||||
|
void AddDestination();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetWorking(bool working);
|
void SetWorking(bool working);
|
||||||
void UpdateStatusText();
|
void UpdateStatusText();
|
||||||
void UpdateProgress();
|
void UpdateProgress();
|
||||||
|
QString TrimPath(const QString& path) const;
|
||||||
|
QString GetOutputFileName(const QString& input,
|
||||||
|
const TranscoderPreset& preset) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui_TranscodeDialog* ui_;
|
Ui_TranscodeDialog* ui_;
|
||||||
|
@ -98,7 +98,7 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Output options</string>
|
<string>Output options</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QFormLayout" name="formLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -107,25 +107,21 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<widget class="QComboBox" name="format">
|
||||||
<item>
|
<property name="sizePolicy">
|
||||||
<widget class="QComboBox" name="format">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
<property name="sizePolicy">
|
<horstretch>0</horstretch>
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<verstretch>0</verstretch>
|
||||||
<horstretch>0</horstretch>
|
</sizepolicy>
|
||||||
<verstretch>0</verstretch>
|
</property>
|
||||||
</sizepolicy>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
</widget>
|
<item row="0" column="2">
|
||||||
</item>
|
<widget class="QPushButton" name="options">
|
||||||
<item>
|
<property name="text">
|
||||||
<widget class="QPushButton" name="options">
|
<string>Options...</string>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Options...</string>
|
</widget>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
@ -136,6 +132,15 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QComboBox" name="destination">
|
<widget class="QComboBox" name="destination">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Alongside the originals</string>
|
<string>Alongside the originals</string>
|
||||||
@ -143,6 +148,13 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QPushButton" name="select">
|
||||||
|
<property name="text">
|
||||||
|
<string>Select...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -196,7 +208,6 @@
|
|||||||
<tabstop>add</tabstop>
|
<tabstop>add</tabstop>
|
||||||
<tabstop>remove</tabstop>
|
<tabstop>remove</tabstop>
|
||||||
<tabstop>format</tabstop>
|
<tabstop>format</tabstop>
|
||||||
<tabstop>destination</tabstop>
|
|
||||||
<tabstop>button_box</tabstop>
|
<tabstop>button_box</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -27,10 +27,11 @@ class AlbumCoverFetcher;
|
|||||||
class AlbumCoverSearcher;
|
class AlbumCoverSearcher;
|
||||||
class Application;
|
class Application;
|
||||||
class CoverFromURLDialog;
|
class CoverFromURLDialog;
|
||||||
class CoverSearchStatistics;
|
|
||||||
class QFileDialog;
|
class QFileDialog;
|
||||||
class Song;
|
class Song;
|
||||||
|
|
||||||
|
struct CoverSearchStatistics;
|
||||||
|
|
||||||
// Controller for the common album cover related menu options.
|
// Controller for the common album cover related menu options.
|
||||||
class AlbumCoverChoiceController : public QWidget {
|
class AlbumCoverChoiceController : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -511,6 +511,7 @@ MainWindow::MainWindow(Application* app,
|
|||||||
playlist_copy_to_device_ = playlist_menu_->addAction(IconLoader::Load("multimedia-player-ipod-mini-blue"), tr("Copy to device..."), this, SLOT(PlaylistCopyToDevice()));
|
playlist_copy_to_device_ = playlist_menu_->addAction(IconLoader::Load("multimedia-player-ipod-mini-blue"), tr("Copy to device..."), this, SLOT(PlaylistCopyToDevice()));
|
||||||
playlist_delete_ = playlist_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, SLOT(PlaylistDelete()));
|
playlist_delete_ = playlist_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, SLOT(PlaylistDelete()));
|
||||||
playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, SLOT(PlaylistOpenInBrowser()));
|
playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, SLOT(PlaylistOpenInBrowser()));
|
||||||
|
playlist_show_in_library_ = playlist_menu_->addAction(IconLoader::Load("edit-find"), tr("Show in library..."), this, SLOT(ShowInLibrary()));
|
||||||
playlist_menu_->addSeparator();
|
playlist_menu_->addSeparator();
|
||||||
playlistitem_actions_separator_ = playlist_menu_->addSeparator();
|
playlistitem_actions_separator_ = playlist_menu_->addSeparator();
|
||||||
playlist_menu_->addAction(ui_->action_clear_playlist);
|
playlist_menu_->addAction(ui_->action_clear_playlist);
|
||||||
@ -692,6 +693,10 @@ MainWindow::MainWindow(Application* app,
|
|||||||
app_->playlist_manager()->Init(app_->library_backend(), app_->playlist_backend(),
|
app_->playlist_manager()->Init(app_->library_backend(), app_->playlist_backend(),
|
||||||
ui_->playlist_sequence, ui_->playlist);
|
ui_->playlist_sequence, ui_->playlist);
|
||||||
|
|
||||||
|
// This connection must be done after the playlists have been initialized.
|
||||||
|
connect(this, SIGNAL(StopAfterToggled(bool)),
|
||||||
|
osd_, SLOT(StopAfterToggle(bool)));
|
||||||
|
|
||||||
// We need to connect these global shortcuts here after the playlist have been initialized
|
// We need to connect these global shortcuts here after the playlist have been initialized
|
||||||
connect(global_shortcuts_, SIGNAL(CycleShuffleMode()), app_->playlist_manager()->sequence(), SLOT(CycleShuffleMode()));
|
connect(global_shortcuts_, SIGNAL(CycleShuffleMode()), app_->playlist_manager()->sequence(), SLOT(CycleShuffleMode()));
|
||||||
connect(global_shortcuts_, SIGNAL(CycleRepeatMode()), app_->playlist_manager()->sequence(), SLOT(CycleRepeatMode()));
|
connect(global_shortcuts_, SIGNAL(CycleRepeatMode()), app_->playlist_manager()->sequence(), SLOT(CycleRepeatMode()));
|
||||||
@ -1060,7 +1065,8 @@ void MainWindow::ToggleShowHide() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::StopAfterCurrent() {
|
void MainWindow::StopAfterCurrent() {
|
||||||
app_->playlist_manager()->current()->StopAfter(app_->playlist_manager()->current()->current_row());
|
app_->playlist_manager()->active()->StopAfter(app_->playlist_manager()->active()->current_row());
|
||||||
|
emit StopAfterToggled(app_->playlist_manager()->active()->stop_after_current());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::closeEvent(QCloseEvent* event) {
|
void MainWindow::closeEvent(QCloseEvent* event) {
|
||||||
@ -1357,6 +1363,7 @@ void MainWindow::PlaylistRightClick(const QPoint& global_pos, const QModelIndex&
|
|||||||
ui_->action_edit_value->setVisible(editable);
|
ui_->action_edit_value->setVisible(editable);
|
||||||
ui_->action_remove_from_playlist->setEnabled(!selection.isEmpty());
|
ui_->action_remove_from_playlist->setEnabled(!selection.isEmpty());
|
||||||
|
|
||||||
|
playlist_show_in_library_->setVisible(false);
|
||||||
playlist_copy_to_library_->setVisible(false);
|
playlist_copy_to_library_->setVisible(false);
|
||||||
playlist_move_to_library_->setVisible(false);
|
playlist_move_to_library_->setVisible(false);
|
||||||
playlist_organise_->setVisible(false);
|
playlist_organise_->setVisible(false);
|
||||||
@ -1405,6 +1412,7 @@ void MainWindow::PlaylistRightClick(const QPoint& global_pos, const QModelIndex&
|
|||||||
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
||||||
if (item->IsLocalLibraryItem() && item->Metadata().id() != -1) {
|
if (item->IsLocalLibraryItem() && item->Metadata().id() != -1) {
|
||||||
playlist_organise_->setVisible(editable);
|
playlist_organise_->setVisible(editable);
|
||||||
|
playlist_show_in_library_->setVisible(editable);
|
||||||
} else {
|
} else {
|
||||||
playlist_copy_to_library_->setVisible(editable);
|
playlist_copy_to_library_->setVisible(editable);
|
||||||
playlist_move_to_library_->setVisible(editable);
|
playlist_move_to_library_->setVisible(editable);
|
||||||
@ -1680,6 +1688,22 @@ void MainWindow::AddCDTracks() {
|
|||||||
AddToPlaylist(data);
|
AddToPlaylist(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::ShowInLibrary() {
|
||||||
|
// Show the first valid selected track artist/album in LibraryView
|
||||||
|
QModelIndexList proxy_indexes = ui_->playlist->view()->selectionModel()->selectedRows();
|
||||||
|
SongList songs;
|
||||||
|
|
||||||
|
foreach (const QModelIndex& proxy_index, proxy_indexes) {
|
||||||
|
QModelIndex index = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
||||||
|
if (app_->playlist_manager()->current()->item_at(index.row())->IsLocalLibraryItem()) {
|
||||||
|
songs << app_->playlist_manager()->current()->item_at(index.row())->Metadata();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QString search = "artist:"+songs[0].artist()+" album:"+songs[0].album();
|
||||||
|
library_view_->filter()->ShowInLibrary(search);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::PlaylistRemoveCurrent() {
|
void MainWindow::PlaylistRemoveCurrent() {
|
||||||
ui_->playlist->view()->RemoveSelected();
|
ui_->playlist->view()->RemoveSelected();
|
||||||
}
|
}
|
||||||
|
@ -136,6 +136,10 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
void Activate();
|
void Activate();
|
||||||
bool LoadUrl(const QString& url);
|
bool LoadUrl(const QString& url);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
// Signals that stop playing after track was toggled.
|
||||||
|
void StopAfterToggled(bool stop);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void FilePathChanged(const QString& path);
|
void FilePathChanged(const QString& path);
|
||||||
|
|
||||||
@ -169,6 +173,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
void PlaylistOrganiseSelected(bool copy);
|
void PlaylistOrganiseSelected(bool copy);
|
||||||
void PlaylistDelete();
|
void PlaylistDelete();
|
||||||
void PlaylistOpenInBrowser();
|
void PlaylistOpenInBrowser();
|
||||||
|
void ShowInLibrary();
|
||||||
|
|
||||||
void ChangeLibraryQueryMode(QAction* action);
|
void ChangeLibraryQueryMode(QAction* action);
|
||||||
|
|
||||||
@ -329,6 +334,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
QAction* playlist_stop_after_;
|
QAction* playlist_stop_after_;
|
||||||
QAction* playlist_undoredo_;
|
QAction* playlist_undoredo_;
|
||||||
QAction* playlist_organise_;
|
QAction* playlist_organise_;
|
||||||
|
QAction* playlist_show_in_library_;
|
||||||
QAction* playlist_copy_to_library_;
|
QAction* playlist_copy_to_library_;
|
||||||
QAction* playlist_move_to_library_;
|
QAction* playlist_move_to_library_;
|
||||||
QAction* playlist_copy_to_device_;
|
QAction* playlist_copy_to_device_;
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
const char* FileView::kFileFilter = "*.mp3 *.ogg *.flac *.mpc *.m4a *.aac *.wma "
|
const char* FileView::kFileFilter = "*.mp3 *.ogg *.flac *.mpc *.m4a *.aac *.wma "
|
||||||
"*.mp4 *.spx *.wav *.m3u *.m3u8 *.pls *.xspf "
|
"*.mp4 *.spx *.wav *.m3u *.m3u8 *.pls *.xspf "
|
||||||
"*.asx *.asxini *.cue *.ape *.wv *.mka *.opus "
|
"*.asx *.asxini *.cue *.ape *.wv *.mka *.opus "
|
||||||
"*.oga *.mka";
|
"*.oga *.mka *.mp2";
|
||||||
|
|
||||||
FileView::FileView(QWidget* parent)
|
FileView::FileView(QWidget* parent)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
|
@ -32,7 +32,8 @@ ExtendedEditor::ExtendedEditor(QWidget* widget, int extra_right_padding,
|
|||||||
reset_button_(new QToolButton(widget)),
|
reset_button_(new QToolButton(widget)),
|
||||||
extra_right_padding_(extra_right_padding),
|
extra_right_padding_(extra_right_padding),
|
||||||
draw_hint_(draw_hint),
|
draw_hint_(draw_hint),
|
||||||
font_point_size_(widget->font().pointSizeF() - 1)
|
font_point_size_(widget->font().pointSizeF() - 1),
|
||||||
|
is_rtl_(false)
|
||||||
{
|
{
|
||||||
clear_button_->setIcon(IconLoader::Load("edit-clear-locationbar-ltr"));
|
clear_button_->setIcon(IconLoader::Load("edit-clear-locationbar-ltr"));
|
||||||
clear_button_->setIconSize(QSize(16, 16));
|
clear_button_->setIconSize(QSize(16, 16));
|
||||||
@ -118,15 +119,22 @@ void ExtendedEditor::Paint(QPaintDevice* device) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
clear_button_->setVisible(has_clear_button_);
|
clear_button_->setVisible(has_clear_button_);
|
||||||
|
Resize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtendedEditor::Resize() {
|
void ExtendedEditor::Resize() {
|
||||||
const QSize sz = clear_button_->sizeHint();
|
const QSize sz = clear_button_->sizeHint();
|
||||||
const int frame_width = widget_->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
const int frame_width = widget_->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
||||||
clear_button_->move(frame_width, (widget_->rect().height() - sz.height()) / 2);
|
const int y = (widget_->rect().height() - sz.height()) / 2;
|
||||||
reset_button_->move(widget_->width() - frame_width - sz.width() - extra_right_padding_,
|
|
||||||
(widget_->rect().height() - sz.height()) / 2);
|
clear_button_->move(frame_width, y);
|
||||||
|
|
||||||
|
if (!is_rtl_) {
|
||||||
|
reset_button_->move(widget_->width() - frame_width - sz.width() - extra_right_padding_, y);
|
||||||
|
} else {
|
||||||
|
reset_button_->move((has_clear_button() ? sz.width() + 4 : 0) + frame_width, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -137,6 +145,16 @@ LineEdit::LineEdit(QWidget* parent)
|
|||||||
connect(reset_button_, SIGNAL(clicked()), SIGNAL(Reset()));
|
connect(reset_button_, SIGNAL(clicked()), SIGNAL(Reset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LineEdit::set_text(const QString& text) {
|
||||||
|
QLineEdit::setText(text);
|
||||||
|
|
||||||
|
// For some reason Qt will detect any text with LTR at the end as LTR, so instead
|
||||||
|
// compare only the first character
|
||||||
|
if (!text.isEmpty()) {
|
||||||
|
set_rtl(QString(text.at(0)).isRightToLeft());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LineEdit::paintEvent(QPaintEvent* e) {
|
void LineEdit::paintEvent(QPaintEvent* e) {
|
||||||
QLineEdit::paintEvent(e);
|
QLineEdit::paintEvent(e);
|
||||||
Paint(this);
|
Paint(this);
|
||||||
|
@ -86,6 +86,7 @@ protected:
|
|||||||
int extra_right_padding_;
|
int extra_right_padding_;
|
||||||
bool draw_hint_;
|
bool draw_hint_;
|
||||||
qreal font_point_size_;
|
qreal font_point_size_;
|
||||||
|
bool is_rtl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LineEdit : public QLineEdit,
|
class LineEdit : public QLineEdit,
|
||||||
@ -102,13 +103,17 @@ public:
|
|||||||
// ExtendedEditor
|
// ExtendedEditor
|
||||||
void set_focus() { QLineEdit::setFocus(); }
|
void set_focus() { QLineEdit::setFocus(); }
|
||||||
QString text() const { return QLineEdit::text(); }
|
QString text() const { return QLineEdit::text(); }
|
||||||
void set_text(const QString& text) { QLineEdit::setText(text); }
|
void set_text(const QString& text);
|
||||||
void set_enabled(bool enabled) { QLineEdit::setEnabled(enabled); }
|
void set_enabled(bool enabled) { QLineEdit::setEnabled(enabled); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent*);
|
void paintEvent(QPaintEvent*);
|
||||||
void resizeEvent(QResizeEvent*);
|
void resizeEvent(QResizeEvent*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool is_rtl() const { return is_rtl_; }
|
||||||
|
void set_rtl(bool rtl) { is_rtl_ = rtl; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Reset();
|
void Reset();
|
||||||
};
|
};
|
||||||
|
@ -166,6 +166,11 @@ void OSD::Stopped() {
|
|||||||
ShowMessage(QCoreApplication::applicationName(), tr("Stopped"));
|
ShowMessage(QCoreApplication::applicationName(), tr("Stopped"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OSD::StopAfterToggle(bool stop) {
|
||||||
|
ShowMessage(QCoreApplication::applicationName(),
|
||||||
|
tr("Stop playing after track: %1").arg(stop ? tr("On") : tr("Off")));
|
||||||
|
}
|
||||||
|
|
||||||
void OSD::PlaylistFinished() {
|
void OSD::PlaylistFinished() {
|
||||||
// We get a PlaylistFinished followed by a Stopped from the player
|
// We get a PlaylistFinished followed by a Stopped from the player
|
||||||
ignore_next_stopped_ = true;
|
ignore_next_stopped_ = true;
|
||||||
|
@ -71,6 +71,7 @@ class OSD : public QObject {
|
|||||||
|
|
||||||
void Paused();
|
void Paused();
|
||||||
void Stopped();
|
void Stopped();
|
||||||
|
void StopAfterToggle(bool stop);
|
||||||
void PlaylistFinished();
|
void PlaylistFinished();
|
||||||
void VolumeChanged(int value);
|
void VolumeChanged(int value);
|
||||||
void MagnatuneDownloadFinished(const QStringList& albums);
|
void MagnatuneDownloadFinished(const QStringList& albums);
|
||||||
|
@ -38,7 +38,7 @@ TrackSlider::TrackSlider(QWidget* parent)
|
|||||||
{
|
{
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
|
|
||||||
QFont font("Courier");
|
QFont font("Comic Sans MS");
|
||||||
ui_->elapsed->setFont(font);
|
ui_->elapsed->setFont(font);
|
||||||
ui_->remaining->setFont(font);
|
ui_->remaining->setFont(font);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user