diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 99f56e808..bfc906ae2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -83,7 +83,9 @@ ENDIF() SET( tomahawkUI ${tomahawkUI} TomahawkWindow.ui DiagnosticsDialog.ui - StackedSettingsDialog.ui + Settings_Accounts.ui + Settings_Advanced.ui + Settings_Collection.ui ProxyDialog.ui AudioControls.ui diff --git a/src/SettingsDialog.cpp b/src/SettingsDialog.cpp index 06217c8aa..4aafe6386 100644 --- a/src/SettingsDialog.cpp +++ b/src/SettingsDialog.cpp @@ -53,75 +53,78 @@ #include "utils/Logger.h" #include "accounts/AccountFactoryWrapper.h" #include "accounts/spotify/SpotifyAccount.h" +#include "thirdparty/Qocoa/qtoolbartabdialog.h" #include "ui_ProxyDialog.h" -#include "ui_StackedSettingsDialog.h" +#include "ui_Settings_Accounts.h" +#include "ui_Settings_Collection.h" +#include "ui_Settings_Advanced.h" using namespace Tomahawk; using namespace Accounts; -SettingsDialog::SettingsDialog( QWidget *parent ) - : QDialog( parent ) - , ui( new Ui_StackedSettingsDialog ) - , m_proxySettings( this ) +SettingsDialog::SettingsDialog(QObject *parent ) + : QObject( parent ) + , m_accountsWidgetUi( new Ui_Settings_Accounts ) + , m_accountsWidget( new QWidget ) + , m_collectionWidgetUi( new Ui_Settings_Collection ) + , m_collectionWidget( new QWidget ) + , m_advancedWidgetUi( new Ui_Settings_Advanced ) + , m_advancedWidget( new QWidget ) + , m_proxySettings( 0 ) , m_rejected( false ) , m_restartRequired( false ) , m_accountModel( 0 ) , m_sipSpinner( 0 ) { - ui->setupUi( this ); + m_accountsWidgetUi->setupUi( m_accountsWidget ); + m_collectionWidgetUi->setupUi( m_collectionWidget ); + m_advancedWidgetUi->setupUi( m_advancedWidget ); + + m_dialog = new QToolbarTabDialog; + TomahawkSettings* s = TomahawkSettings::instance(); - TomahawkUtils::unmarginLayout( layout() ); - TomahawkUtils::unmarginLayout( ui->horizontalLayout ); +// TomahawkUtils::unmarginLayout( layout() ); +// TomahawkUtils::unmarginLayout( ui->horizontalLayout ); -#ifdef Q_WS_X11 - ui->stackedWidget->setContentsMargins( 4, 4, 4, 4 ); -#else - ui->stackedWidget->setContentsMargins( 4, 4, 4, 0 ); -#endif - ui->checkBoxReporter->setChecked( s->crashReporterEnabled() ); - ui->checkBoxHttp->setChecked( s->httpEnabled() ); - - QFrame *sepLine = new QFrame( this ); - sepLine->setFrameShape( QFrame::HLine ); - sepLine->setFrameShadow( QFrame::Sunken ); - ui->horizontalLayout->insertWidget( 0, sepLine ); - - m_toolBar = new QToolBar( tr( "Tomahawk Settings" ), this ); - ui->horizontalLayout->insertWidget( 0, m_toolBar ); - m_toolBar->setToolButtonStyle( Qt::ToolButtonTextUnderIcon ); +//#ifdef Q_WS_X11 +// ui->stackedWidget->setContentsMargins( 4, 4, 4, 4 ); +//#else +// ui->stackedWidget->setContentsMargins( 4, 4, 4, 0 ); +//#endif + m_advancedWidgetUi->checkBoxReporter->setChecked( s->crashReporterEnabled() ); + m_advancedWidgetUi->checkBoxHttp->setChecked( s->httpEnabled() ); //Network settings TomahawkSettings::ExternalAddressMode mode = TomahawkSettings::instance()->externalAddressMode(); if ( mode == TomahawkSettings::Lan ) - ui->lanOnlyRadioButton->setChecked( true ); + m_advancedWidgetUi->lanOnlyRadioButton->setChecked( true ); else if ( mode == TomahawkSettings::Static ) - ui->staticIpRadioButton->setChecked( true ); + m_advancedWidgetUi->staticIpRadioButton->setChecked( true ); else - ui->upnpRadioButton->setChecked( true ); + m_advancedWidgetUi->upnpRadioButton->setChecked( true ); - ui->staticHostNamePortLabel->setEnabled( ui->staticIpRadioButton->isChecked() ); - ui->staticHostName->setEnabled( ui->staticIpRadioButton->isChecked() ); - ui->staticPort->setEnabled( ui->staticIpRadioButton->isChecked() ); - ui->staticHostNameLabel->setEnabled( ui->staticIpRadioButton->isChecked() ); - ui->staticPortLabel->setEnabled( ui->staticIpRadioButton->isChecked() ); + m_advancedWidgetUi->staticHostNamePortLabel->setEnabled( m_advancedWidgetUi->staticIpRadioButton->isChecked() ); + m_advancedWidgetUi->staticHostName->setEnabled( m_advancedWidgetUi->staticIpRadioButton->isChecked() ); + m_advancedWidgetUi->staticPort->setEnabled( m_advancedWidgetUi->staticIpRadioButton->isChecked() ); + m_advancedWidgetUi->staticHostNameLabel->setEnabled( m_advancedWidgetUi->staticIpRadioButton->isChecked() ); + m_advancedWidgetUi->staticPortLabel->setEnabled( m_advancedWidgetUi->staticIpRadioButton->isChecked() ); bool useProxy = TomahawkSettings::instance()->proxyType() == QNetworkProxy::Socks5Proxy; - ui->enableProxyCheckBox->setChecked( useProxy ); - ui->proxyButton->setEnabled( useProxy ); + m_advancedWidgetUi->enableProxyCheckBox->setChecked( useProxy ); + m_advancedWidgetUi->proxyButton->setEnabled( useProxy ); - ui->aclEntryClearButton->setEnabled( TomahawkSettings::instance()->aclEntries().size() > 0 ); - connect( ui->aclEntryClearButton, SIGNAL( clicked( bool ) ), this, SLOT( aclEntryClearButtonClicked() ) ); + m_advancedWidgetUi->aclEntryClearButton->setEnabled( TomahawkSettings::instance()->aclEntries().size() > 0 ); + connect( m_advancedWidgetUi->aclEntryClearButton, SIGNAL( clicked( bool ) ), this, SLOT( aclEntryClearButtonClicked() ) ); - createIcons(); -#ifdef Q_WS_X11 - setContentsMargins( 4, 4, 4, 4 ); -#elif defined( Q_OS_MAC ) - setContentsMargins( 0, 0, 0, 4 ); -#else - setContentsMargins( 0, 4, 4, 4 ); -#endif +//#ifdef Q_WS_X11 +// setContentsMargins( 4, 4, 4, 4 ); +//#elif defined( Q_OS_MAC ) +// setContentsMargins( 0, 0, 0, 4 ); +//#else +// setContentsMargins( 0, 4, 4, 4 ); +//#endif #ifdef Q_WS_MAC // Avoid resize handles on sheets on osx @@ -132,14 +135,14 @@ SettingsDialog::SettingsDialog( QWidget *parent ) // Accounts AccountDelegate* accountDelegate = new AccountDelegate( this ); - ui->accountsView->setItemDelegate( accountDelegate ); - ui->accountsView->setContextMenuPolicy( Qt::CustomContextMenu ); - ui->accountsView->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); - ui->accountsView->setMouseTracking( true ); + m_accountsWidgetUi->accountsView->setItemDelegate( accountDelegate ); + m_accountsWidgetUi->accountsView->setContextMenuPolicy( Qt::CustomContextMenu ); + m_accountsWidgetUi->accountsView->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); + m_accountsWidgetUi->accountsView->setMouseTracking( true ); connect( accountDelegate, SIGNAL( openConfig( Tomahawk::Accounts::Account* ) ), this, SLOT( openAccountConfig( Tomahawk::Accounts::Account* ) ) ); connect( accountDelegate, SIGNAL( openConfig( Tomahawk::Accounts::AccountFactory* ) ), this, SLOT( openAccountFactoryConfig( Tomahawk::Accounts::AccountFactory* ) ) ); - connect( accountDelegate, SIGNAL( update( QModelIndex ) ), ui->accountsView, SLOT( update( QModelIndex ) ) ); + connect( accountDelegate, SIGNAL( update( QModelIndex ) ), m_accountsWidgetUi->accountsView, SLOT( update( QModelIndex ) ) ); m_accountModel = new AccountModel( this ); m_accountProxy = new AccountModelFilterProxy( m_accountModel ); @@ -150,58 +153,58 @@ SettingsDialog::SettingsDialog( QWidget *parent ) connect( m_accountProxy, SIGNAL( errorInstalling( QPersistentModelIndex ) ), accountDelegate, SLOT( errorInstalling(QPersistentModelIndex) ) ); connect( m_accountProxy, SIGNAL( scrollTo( QModelIndex ) ), this, SLOT( scrollTo( QModelIndex ) ) ); - ui->accountsView->setModel( m_accountProxy ); + m_accountsWidgetUi->accountsView->setModel( m_accountProxy ); - connect( ui->installFromFileBtn, SIGNAL( clicked( bool ) ), this, SLOT( installFromFile() ) ); + connect( m_accountsWidgetUi->installFromFileBtn, SIGNAL( clicked( bool ) ), this, SLOT( installFromFile() ) ); connect( m_accountModel, SIGNAL( createAccount( Tomahawk::Accounts::AccountFactory* ) ), this, SLOT( createAccountFromFactory( Tomahawk::Accounts::AccountFactory* ) ) ); - ui->accountsFilterCombo->addItem( tr( "All" ), Accounts::NoType ); - ui->accountsFilterCombo->addItem( accountTypeToString( SipType ), SipType ); - ui->accountsFilterCombo->addItem( accountTypeToString( ResolverType ), ResolverType ); - ui->accountsFilterCombo->addItem( accountTypeToString( StatusPushType ), StatusPushType ); + m_accountsWidgetUi->accountsFilterCombo->addItem( tr( "All" ), Accounts::NoType ); + m_accountsWidgetUi->accountsFilterCombo->addItem( accountTypeToString( SipType ), SipType ); + m_accountsWidgetUi->accountsFilterCombo->addItem( accountTypeToString( ResolverType ), ResolverType ); + m_accountsWidgetUi->accountsFilterCombo->addItem( accountTypeToString( StatusPushType ), StatusPushType ); - connect( ui->accountsFilterCombo, SIGNAL( activated( int ) ), this, SLOT( accountsFilterChanged( int ) ) ); + connect( m_accountsWidgetUi->accountsFilterCombo, SIGNAL( activated( int ) ), this, SLOT( accountsFilterChanged( int ) ) ); if ( !Servent::instance()->isReady() ) { - m_sipSpinner = new AnimatedSpinner( ui->accountsView ); + m_sipSpinner = new AnimatedSpinner( m_accountsWidgetUi->accountsView ); m_sipSpinner->fadeIn(); connect( Servent::instance(), SIGNAL( ready() ), this, SLOT( serventReady() ) ); } // ADVANCED - ui->staticHostName->setText( s->externalHostname() ); - ui->staticPort->setValue( s->externalPort() ); - ui->proxyButton->setVisible( true ); + m_advancedWidgetUi->staticHostName->setText( s->externalHostname() ); + m_advancedWidgetUi->staticPort->setValue( s->externalPort() ); + m_advancedWidgetUi->proxyButton->setVisible( true ); - ui->checkBoxWatchForChanges->setChecked( s->watchForChanges() ); - ui->scannerTimeSpinBox->setValue( s->scannerTime() ); - ui->enableEchonestCatalog->setChecked( s->enableEchonestCatalogs() ); + m_collectionWidgetUi->checkBoxWatchForChanges->setChecked( s->watchForChanges() ); + m_collectionWidgetUi->scannerTimeSpinBox->setValue( s->scannerTime() ); + m_collectionWidgetUi->enableEchonestCatalog->setChecked( s->enableEchonestCatalogs() ); - connect( ui->checkBoxWatchForChanges, SIGNAL( clicked( bool ) ), SLOT( updateScanOptionsView() ) ); + connect( m_collectionWidgetUi->checkBoxWatchForChanges, SIGNAL( clicked( bool ) ), SLOT( updateScanOptionsView() ) ); - if ( ui->checkBoxWatchForChanges->isChecked() ) + if ( m_collectionWidgetUi->checkBoxWatchForChanges->isChecked() ) { - ui->scanTimeLabel->show(); - ui->scannerTimeSpinBox->show(); + m_collectionWidgetUi->scanTimeLabel->show(); + m_collectionWidgetUi->scannerTimeSpinBox->show(); } else { - ui->scanTimeLabel->hide(); - ui->scannerTimeSpinBox->hide(); + m_collectionWidgetUi->scanTimeLabel->hide(); + m_collectionWidgetUi->scannerTimeSpinBox->hide(); } foreach ( const QString& dir, TomahawkSettings::instance()->scannerPaths() ) { - ui->dirTree->checkPath( dir, Qt::Checked ); + m_collectionWidgetUi->dirTree->checkPath( dir, Qt::Checked ); } - ui->advancedPage->setMinimumSize( ui->advancedPage->sizeHint() ); +// m_collectionWidgetUi->advancedPage->setMinimumSize( ui->advancedPage->sizeHint() ); - int buttonsWidth = qMax( ui->proxyButton->sizeHint().width(), - ui->aclEntryClearButton->sizeHint().width() ); - ui->proxyButton->setFixedWidth( buttonsWidth ); - ui->aclEntryClearButton->setFixedWidth( buttonsWidth ); + int buttonsWidth = qMax( m_advancedWidgetUi->proxyButton->sizeHint().width(), + m_advancedWidgetUi->aclEntryClearButton->sizeHint().width() ); + m_advancedWidgetUi->proxyButton->setFixedWidth( buttonsWidth ); + m_advancedWidgetUi->aclEntryClearButton->setFixedWidth( buttonsWidth ); // NOW PLAYING @@ -211,15 +214,30 @@ SettingsDialog::SettingsDialog( QWidget *parent ) // ui->checkBoxEnableAdium->hide(); // #endif - connect( ui->proxyButton, SIGNAL( clicked() ), SLOT( showProxySettings() ) ); - connect( ui->lanOnlyRadioButton, SIGNAL( toggled(bool) ), SLOT( requiresRestart() ) ); - connect( ui->staticIpRadioButton, SIGNAL( toggled(bool) ), SLOT( requiresRestart() ) ); - connect( ui->upnpRadioButton, SIGNAL( toggled(bool) ), SLOT( requiresRestart() ) ); - connect( ui->lanOnlyRadioButton, SIGNAL( toggled(bool) ), SLOT( toggleRemoteMode() ) ); - connect( ui->staticIpRadioButton, SIGNAL( toggled(bool) ), SLOT( toggleRemoteMode() ) ); - connect( ui->upnpRadioButton, SIGNAL( toggled(bool) ), SLOT( toggleRemoteMode() ) ); - connect( ui->enableProxyCheckBox, SIGNAL( toggled(bool) ), SLOT( toggleProxyEnabled() ) ); - connect( this, SIGNAL( rejected() ), SLOT( onRejected() ) ); + m_dialog->addTab( m_accountsWidget, QPixmap( RESPATH "images/account-settings.png" ), tr( "Services" ), tr( "Services
" + "Configure the accounts and services used by Tomahawk " + "to search and retrieve music, find your friends and " + "update your status." )); + + m_dialog->addTab( m_collectionWidget, QPixmap( RESPATH "images/music-settings.png" ), tr( "Collection" ), tr("Collection
" + "Manage how Tomahawk finds music on your computer." )); + + m_dialog->addTab( m_advancedWidget, QPixmap( RESPATH "images/advanced-settings.png" ), tr( "Advanced" ), tr( "Advanced
" + "Configure Tomahawk's advanced settings, including " + "network connectivity settings, browser interaction " + "and more." )); + + m_dialog->setCurrentIndex( 0 ); + + connect( m_advancedWidgetUi->proxyButton, SIGNAL( clicked() ), SLOT( showProxySettings() ) ); + connect( m_advancedWidgetUi->lanOnlyRadioButton, SIGNAL( toggled(bool) ), SLOT( requiresRestart() ) ); + connect( m_advancedWidgetUi->staticIpRadioButton, SIGNAL( toggled(bool) ), SLOT( requiresRestart() ) ); + connect( m_advancedWidgetUi->upnpRadioButton, SIGNAL( toggled(bool) ), SLOT( requiresRestart() ) ); + connect( m_advancedWidgetUi->lanOnlyRadioButton, SIGNAL( toggled(bool) ), SLOT( toggleRemoteMode() ) ); + connect( m_advancedWidgetUi->staticIpRadioButton, SIGNAL( toggled(bool) ), SLOT( toggleRemoteMode() ) ); + connect( m_advancedWidgetUi->upnpRadioButton, SIGNAL( toggled(bool) ), SLOT( toggleRemoteMode() ) ); + connect( m_advancedWidgetUi->enableProxyCheckBox, SIGNAL( toggled(bool) ), SLOT( toggleProxyEnabled() ) ); +// connect( this, SIGNAL( rejected() ), SLOT( onRejected() ) ); } @@ -231,18 +249,18 @@ SettingsDialog::~SettingsDialog() { TomahawkSettings* s = TomahawkSettings::instance(); - s->setCrashReporterEnabled( ui->checkBoxReporter->checkState() == Qt::Checked ); - s->setHttpEnabled( ui->checkBoxHttp->checkState() == Qt::Checked ); - s->setProxyType( ui->enableProxyCheckBox->isChecked() ? QNetworkProxy::Socks5Proxy : QNetworkProxy::NoProxy ); - s->setExternalAddressMode( ui->upnpRadioButton->isChecked() ? TomahawkSettings::Upnp : ( ui->lanOnlyRadioButton->isChecked() ? TomahawkSettings::Lan : TomahawkSettings::Static ) ); + s->setCrashReporterEnabled( m_advancedWidgetUi->checkBoxReporter->checkState() == Qt::Checked ); + s->setHttpEnabled( m_advancedWidgetUi->checkBoxHttp->checkState() == Qt::Checked ); + s->setProxyType( m_advancedWidgetUi->enableProxyCheckBox->isChecked() ? QNetworkProxy::Socks5Proxy : QNetworkProxy::NoProxy ); + s->setExternalAddressMode( m_advancedWidgetUi->upnpRadioButton->isChecked() ? TomahawkSettings::Upnp : ( m_advancedWidgetUi->lanOnlyRadioButton->isChecked() ? TomahawkSettings::Lan : TomahawkSettings::Static ) ); - s->setExternalHostname( ui->staticHostName->text() ); - s->setExternalPort( ui->staticPort->value() ); + s->setExternalHostname( m_advancedWidgetUi->staticHostName->text() ); + s->setExternalPort( m_advancedWidgetUi->staticPort->value() ); - s->setScannerPaths( ui->dirTree->getCheckedPaths() ); - s->setWatchForChanges( ui->checkBoxWatchForChanges->isChecked() ); - s->setScannerTime( ui->scannerTimeSpinBox->value() ); - s->setEnableEchonestCatalogs( ui->enableEchonestCatalog->isChecked() ); + s->setScannerPaths( m_collectionWidgetUi->dirTree->getCheckedPaths() ); + s->setWatchForChanges( m_collectionWidgetUi->checkBoxWatchForChanges->isChecked() ); + s->setScannerTime( m_collectionWidgetUi->scannerTimeSpinBox->value() ); + s->setEnableEchonestCatalogs( m_collectionWidgetUi->enableEchonestCatalog->isChecked() ); // s->setNowPlayingEnabled( ui->checkBoxEnableAdium->isChecked() ); @@ -250,10 +268,10 @@ SettingsDialog::~SettingsDialog() s->sync(); if ( m_restartRequired ) - QMessageBox::information( this, tr( "Information" ), tr( "Some changed settings will not take effect until Tomahawk is restarted" ) ); + QMessageBox::information( 0, tr( "Information" ), tr( "Some changed settings will not take effect until Tomahawk is restarted" ) ); TomahawkUtils::NetworkProxyFactory* proxyFactory = TomahawkUtils::proxyFactory(); - if ( !ui->enableProxyCheckBox->isChecked() ) + if ( !m_advancedWidgetUi->enableProxyCheckBox->isChecked() ) { tDebug() << Q_FUNC_INFO << "Got NoProxy selected"; proxyFactory->setProxy( QNetworkProxy::NoProxy ); @@ -273,10 +291,19 @@ SettingsDialog::~SettingsDialog() else qDebug() << "Settings dialog cancelled, NOT saving prefs."; - delete ui; + m_accountsWidget->deleteLater(); + m_collectionWidget->deleteLater(); + m_advancedWidget->deleteLater(); + m_dialog->deleteLater(); } +void +SettingsDialog::show() +{ + m_dialog->show(); +} + void SettingsDialog::serventReady() { @@ -284,71 +311,15 @@ SettingsDialog::serventReady() } -void -SettingsDialog::createIcons() -{ - ensurePolished(); - - m_settingsGroup = new QActionGroup( m_toolBar ); - - QWidget *leftSpacer = new QWidget( m_toolBar ); - leftSpacer->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); - m_toolBar->addWidget( leftSpacer ); - - QAction *accountsAction = new QAction( QIcon( RESPATH "images/account-settings.png" ), - tr( "Services" ), - m_toolBar ); - accountsAction->setCheckable( true ); - accountsAction->setToolTip( tr( "Services
" - "Configure the accounts and services used by Tomahawk " - "to search and retrieve music, find your friends and " - "update your status." ) ); - m_settingsGroup->addAction( accountsAction ); - - QAction *musicAction = new QAction( QIcon( RESPATH "images/music-settings.png" ), - tr( "Collection" ), - m_toolBar ); - musicAction->setCheckable( true ); - musicAction->setToolTip( tr( "Collection
" - "Manage how Tomahawk finds music on your computer." ) ); - m_settingsGroup->addAction( musicAction ); - - - QAction *advancedAction = new QAction( QIcon( RESPATH "images/advanced-settings.png" ), - tr( "Advanced" ), - m_toolBar ); - advancedAction->setCheckable( true ); - advancedAction->setToolTip( tr( "Advanced
" - "Configure Tomahawk's advanced settings, including " - "network connectivity settings, browser interaction " - "and more." ) ); - m_settingsGroup->addAction( advancedAction ); - - m_settingsGroup->setExclusive( true ); - - m_toolBar->addActions( m_settingsGroup->actions() ); - - QWidget *rightSpacer = new QWidget( m_toolBar ); - rightSpacer->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); - m_toolBar->addWidget( rightSpacer ); - - connect( m_settingsGroup, SIGNAL( triggered( QAction * ) ), - this, SLOT( changePage( QAction * ) ) ); - - accountsAction->setChecked( true ); - changePage( accountsAction ); -} - - -void -SettingsDialog::changePage( QAction *action ) -{ - int index = m_settingsGroup->actions().indexOf( action ); - if( ui->stackedWidget->currentIndex() != index ) - { - ui->stackedWidget->setCurrentIndex( index ); - } -} +//void +//SettingsDialog::changePage( QAction *action ) +//{ +// int index = m_settingsGroup->actions().indexOf( action ); +// if( ui->stackedWidget->currentIndex() != index ) +// { +// ui->stackedWidget->setCurrentIndex( index ); +// } +//} void @@ -361,11 +332,12 @@ SettingsDialog::onRejected() void SettingsDialog::changeEvent( QEvent *e ) { - QDialog::changeEvent( e ); switch ( e->type() ) { case QEvent::LanguageChange: - ui->retranslateUi( this ); + m_accountsWidgetUi->retranslateUi( m_accountsWidget ); + m_collectionWidgetUi->retranslateUi( m_collectionWidget ); + m_advancedWidgetUi->retranslateUi( m_advancedWidget ); break; default: @@ -386,33 +358,33 @@ SettingsDialog::showProxySettings() void SettingsDialog::toggleRemoteMode() { - ui->staticHostNamePortLabel->setEnabled( ui->staticIpRadioButton->isChecked() ); - ui->staticHostName->setEnabled( ui->staticIpRadioButton->isChecked() ); - ui->staticPort->setEnabled( ui->staticIpRadioButton->isChecked() ); - ui->staticHostNameLabel->setEnabled( ui->staticIpRadioButton->isChecked() ); - ui->staticPortLabel->setEnabled( ui->staticIpRadioButton->isChecked() ); + m_advancedWidgetUi->staticHostNamePortLabel->setEnabled( m_advancedWidgetUi->staticIpRadioButton->isChecked() ); + m_advancedWidgetUi->staticHostName->setEnabled( m_advancedWidgetUi->staticIpRadioButton->isChecked() ); + m_advancedWidgetUi->staticPort->setEnabled( m_advancedWidgetUi->staticIpRadioButton->isChecked() ); + m_advancedWidgetUi->staticHostNameLabel->setEnabled( m_advancedWidgetUi->staticIpRadioButton->isChecked() ); + m_advancedWidgetUi->staticPortLabel->setEnabled( m_advancedWidgetUi->staticIpRadioButton->isChecked() ); } void SettingsDialog::toggleProxyEnabled() { - ui->proxyButton->setEnabled( ui->enableProxyCheckBox->isChecked() ); + m_advancedWidgetUi->proxyButton->setEnabled( m_advancedWidgetUi->enableProxyCheckBox->isChecked() ); } void SettingsDialog::updateScanOptionsView() { - if ( ui->checkBoxWatchForChanges->isChecked() ) + if ( m_collectionWidgetUi->checkBoxWatchForChanges->isChecked() ) { - ui->scanTimeLabel->show(); - ui->scannerTimeSpinBox->show(); + m_collectionWidgetUi->scanTimeLabel->show(); + m_collectionWidgetUi->scannerTimeSpinBox->show(); } else { - ui->scanTimeLabel->hide(); - ui->scannerTimeSpinBox->hide(); + m_collectionWidgetUi->scanTimeLabel->hide(); + m_collectionWidgetUi->scannerTimeSpinBox->hide(); } } @@ -420,7 +392,7 @@ SettingsDialog::updateScanOptionsView() void SettingsDialog::accountsFilterChanged( int ) { - AccountType filter = static_cast< AccountType >( ui->accountsFilterCombo->itemData( ui->accountsFilterCombo->currentIndex() ).toInt() ); + AccountType filter = static_cast< AccountType >( m_accountsWidgetUi->accountsFilterCombo->itemData( m_accountsWidgetUi->accountsFilterCombo->currentIndex() ).toInt() ); m_accountProxy->setFilterType( filter ); } @@ -451,7 +423,7 @@ SettingsDialog::openAccountFactoryConfig( AccountFactory* factory ) dialog.exec(); #else // on osx a sheet needs to be non-modal - AccountFactoryWrapper* dialog = new AccountFactoryWrapper( factory, this ); + AccountFactoryWrapper* dialog = new AccountFactoryWrapper( factory, 0 ); dialog->show(); #endif } @@ -460,21 +432,21 @@ SettingsDialog::openAccountFactoryConfig( AccountFactory* factory ) void SettingsDialog::createAccountFromFactory( AccountFactory* factory ) { - TomahawkUtils::createAccountFromFactory( factory, this ); + TomahawkUtils::createAccountFromFactory( factory, 0 ); } void SettingsDialog::openAccountConfig( Account* account, bool showDelete ) { - TomahawkUtils::openAccountConfig( account, this, showDelete ); + TomahawkUtils::openAccountConfig( account, 0, showDelete ); } void SettingsDialog::installFromFile() { - const QString resolver = QFileDialog::getOpenFileName( this, tr( "Install resolver from file" ), TomahawkSettings::instance()->scriptDefaultPath() ); + const QString resolver = QFileDialog::getOpenFileName( 0, tr( "Install resolver from file" ), TomahawkSettings::instance()->scriptDefaultPath() ); if( !resolver.isEmpty() ) { @@ -520,7 +492,7 @@ void SettingsDialog::aclEntryClearButtonClicked() { QMessageBox::StandardButton button = QMessageBox::question( - ui->stackedWidget, + 0, tr( "Delete all Access Control entries?" ), tr( "Do you really want to delete all Access Control entries? You will be asked for a decision again for each peer that you connect to." ), QMessageBox::Ok | QMessageBox::Cancel, @@ -529,7 +501,7 @@ SettingsDialog::aclEntryClearButtonClicked() if ( button == QMessageBox::Ok ) { ACLRegistry::instance()->wipeEntries(); - ui->aclEntryClearButton->setEnabled( false ); + m_advancedWidgetUi->aclEntryClearButton->setEnabled( false ); } } @@ -537,7 +509,7 @@ SettingsDialog::aclEntryClearButtonClicked() void SettingsDialog::scrollTo( const QModelIndex& idx ) { - ui->accountsView->scrollTo( idx, QAbstractItemView::PositionAtBottom ); + m_accountsWidgetUi->accountsView->scrollTo( idx, QAbstractItemView::PositionAtBottom ); } diff --git a/src/SettingsDialog.h b/src/SettingsDialog.h index 88cb934a0..e9d9f8032 100644 --- a/src/SettingsDialog.h +++ b/src/SettingsDialog.h @@ -31,14 +31,16 @@ class AnimatedSpinner; class QListWidgetItem; -class Ui_StackedSettingsDialog; +class Ui_Settings_Accounts; +class Ui_Settings_Collection; +class Ui_Settings_Advanced; class SipPlugin; class ResolversModel; class QNetworkReply; +class QToolbarTabDialog; namespace Ui { - class SettingsDialog; class ProxyDialog; } @@ -68,14 +70,15 @@ private: Ui::ProxyDialog* ui; }; -class SettingsDialog : public QDialog +class SettingsDialog : public QObject { Q_OBJECT public: - explicit SettingsDialog( QWidget* parent = 0 ); + explicit SettingsDialog( QObject* parent = 0 ); ~SettingsDialog(); + void show(); protected: void changeEvent( QEvent* e ); @@ -97,7 +100,6 @@ private slots: void updateScanOptionsView(); - void changePage( QAction *action ); void serventReady(); void aclEntryClearButtonClicked(); @@ -107,10 +109,16 @@ private slots: private: void createIcons(); - Ui_StackedSettingsDialog* ui; + Ui_Settings_Accounts* m_accountsWidgetUi; + QWidget* m_accountsWidget; - QToolBar *m_toolBar; - QActionGroup *m_settingsGroup; + Ui_Settings_Collection* m_collectionWidgetUi; + QWidget* m_collectionWidget; + + Ui_Settings_Advanced* m_advancedWidgetUi; + QWidget* m_advancedWidget; + + QToolbarTabDialog* m_dialog; ProxyDialog m_proxySettings; bool m_rejected; diff --git a/src/Settings_Accounts.ui b/src/Settings_Accounts.ui new file mode 100644 index 000000000..b7382c1c5 --- /dev/null +++ b/src/Settings_Accounts.ui @@ -0,0 +1,62 @@ + + + Settings_Accounts + + + + 0 + 0 + 508 + 476 + + + + Form + + + + + + + + Install from file... + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Filter by capability: + + + + + + + + + + + + true + + + + + + + + diff --git a/src/Settings_Advanced.ui b/src/Settings_Advanced.ui new file mode 100644 index 000000000..c13f79b25 --- /dev/null +++ b/src/Settings_Advanced.ui @@ -0,0 +1,262 @@ + + + Settings_Advanced + + + + 0 + 0 + 469 + 475 + + + + Form + + + + + + Remote Peer Connection Method + + + + + + None (outgoing connections only) + + + + + + + Use UPnP to establish port forward (recommended) + + + + + + + Use static external IP address/host name and port + + + + + + + + 0 + 0 + + + + Set this to your external IP address or host name. Make sure to forward the port to this host! + + + true + + + + + + + + + + 0 + 0 + + + + Static Host Name: + + + + + + + + + + + 0 + 0 + + + + Static Port: + + + + + + + 65535 + + + 50210 + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + SOCKS Proxy + + + + + + Use SOCKS Proxy + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Proxy Settings... + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + Other Settings + + + + + + Qt::LeftToRight + + + Allow web browsers to interact with Tomahawk (recommended) + + + true + + + + + + + Qt::LeftToRight + + + Send reports after Tomahawk crashed + + + true + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 40 + 20 + + + + + + + + Clear All Access Control Entries + + + + + + + + + + + + Qt::Vertical + + + + 20 + 13 + + + + + + + + + diff --git a/src/Settings_Collection.ui b/src/Settings_Collection.ui new file mode 100644 index 000000000..3031f1dd8 --- /dev/null +++ b/src/Settings_Collection.ui @@ -0,0 +1,93 @@ + + + Settings_Collection + + + + 0 + 0 + 423 + 388 + + + + Form + + + + + + + + Path to scan for music files: + + + + + + + + + + + + + + The Echo Nest supports keeping track of your catalog metadata + and using it to craft personalized radios. Enabling this option + will allow you (and all your friends) to create automatic playlists + and stations based on your personal taste profile. + + + Upload collection list to The Echo Nest to enable user radio + + + + + + + + 0 + 0 + + + + Watch for changes + + + + + + + + + Time between scans, in seconds: + + + + + + + 60 + + + 999999999 + + + + + + + + + + + + CheckDirTree + QTreeView +
widgets/CheckDirTree.h
+
+
+ + +
diff --git a/src/StackedSettingsDialog.ui b/src/StackedSettingsDialog.ui index af3cfe49d..0377d15dd 100644 --- a/src/StackedSettingsDialog.ui +++ b/src/StackedSettingsDialog.ui @@ -6,8 +6,8 @@ 0 0 - 655 - 500 + 692 + 604 @@ -22,7 +22,7 @@ - 0 + 1 @@ -461,6 +461,12 @@ + buttonBox + + frame_4 + frame_2 + frameNetworkAdvanced + stackedWidget diff --git a/src/TomahawkWindow.cpp b/src/TomahawkWindow.cpp index 22dcdd22a..30491c261 100644 --- a/src/TomahawkWindow.cpp +++ b/src/TomahawkWindow.cpp @@ -810,7 +810,7 @@ void TomahawkWindow::showSettingsDialog() { SettingsDialog win; - win.exec(); + win.show(); } diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index c148deb59..c59e804f3 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -392,6 +392,7 @@ IF( APPLE ) utils/TomahawkUtils_Mac.mm mac/FileHelpers.mm thirdparty/Qocoa/qsearchfield_mac.mm + thirdparty/Qocoa/qtoolbartabdialog_mac.mm widgets/SourceTreePopupDialog_mac.mm ) SET_SOURCE_FILES_PROPERTIES(utils/TomahawkUtils_Mac.mm PROPERTIES COMPILE_FLAGS "-fvisibility=default") @@ -408,7 +409,7 @@ IF( APPLE ) /System/Library/Frameworks/Security.framework ) ELSE( APPLE ) - SET( libGuiSources ${libGuiSources} thirdparty/Qocoa/qsearchfield.cpp ) + SET( libGuiSources ${libGuiSources} thirdparty/Qocoa/qsearchfield.cpp thirdparty/Qocoa/qtoolbartabdialog_nonmac.cpp ) ENDIF( APPLE ) IF(LIBLASTFM_FOUND) diff --git a/src/libtomahawk/accounts/lastfm/LastFmConfig.cpp b/src/libtomahawk/accounts/lastfm/LastFmConfig.cpp index 6a8c98b63..9d985f156 100644 --- a/src/libtomahawk/accounts/lastfm/LastFmConfig.cpp +++ b/src/libtomahawk/accounts/lastfm/LastFmConfig.cpp @@ -294,7 +294,7 @@ LastFmConfig::onLovedFinished( QNetworkReply* reply ) m_ui->progressBar->setValue( thisPage ); foreach ( lastfm::XmlQuery e, loved.children( "track" ) ) { -// tDebug() << "Found:" << e.children( "artist" ).first()["name"].text() << e["name"].text() << e["date"].attribute( "uts" ).toUInt(); + tDebug() << "Found:" << e.children( "artist" ).first()["name"].text() << e["name"].text() << e["date"].attribute( "uts" ).toUInt(); Tomahawk::query_ptr query = Tomahawk::Query::get( e.children( "artist" ).first()["name"].text(), e["name"].text(), QString(), QString(), false ); if ( query.isNull() ) continue; @@ -336,6 +336,8 @@ LastFmConfig::onLovedFinished( QNetworkReply* reply ) bool trackEquality( const Tomahawk::query_ptr& first, const Tomahawk::query_ptr& second ) { + qDebug() << "Comparing:" << first->track() << second->track(); + qDebug() << "==========" << first->artist() << second->artist(); return first->equals( second, true ); } @@ -372,15 +374,20 @@ LastFmConfig::syncLoved() foreach ( const Tomahawk::query_ptr& localLoved, myLoved ) { + qDebug() << "CHECKING FOR LOCAL LOVED ON LAST.FM TOO:" << m_localLoved[ localLoved ].value.toString() << localLoved->track() << localLoved->artist(); QSet< Tomahawk::query_ptr >::const_iterator iter = std::find_if( m_lastfmLoved.begin(), m_lastfmLoved.end(), boost::bind( &trackEquality, _1, boost::ref( localLoved ) ) ); + qDebug() << "Result:" << (iter == m_lastfmLoved.constEnd()); // If we unloved it locally, but it's still loved on last.fm, unlove it if ( m_localLoved[ localLoved ].value.toString() == "false" && iter != m_lastfmLoved.constEnd() ) lastFmToUnlove << localLoved; // If we loved it locally but not loved on last.fm, love it if ( m_localLoved[ localLoved ].value.toString() == "true" && iter == m_lastfmLoved.constEnd() ) + { + qDebug() << "Found Local loved track but not on last.fm!:" << localLoved->track() << localLoved->artist(); lastFmToLove << localLoved; + } } foreach ( const Tomahawk::query_ptr& track, localToLove ) diff --git a/src/libtomahawk/thirdparty/Qocoa/qtoolbartabdialog.h b/src/libtomahawk/thirdparty/Qocoa/qtoolbartabdialog.h new file mode 100644 index 000000000..3949bd6f9 --- /dev/null +++ b/src/libtomahawk/thirdparty/Qocoa/qtoolbartabdialog.h @@ -0,0 +1,48 @@ +#ifndef QTOOLBARTABWIDGET_H +#define QTOOLBARTABWIDGET_H + +#include +#include +#include + +#include "DllMacro.h" + +class QToolbarTabDialogPrivate; + +class QAction; + +/** + Dialog with a toolbar that behaves like a tab widget. + + Note that on OS X there are no OK/Cancel buttons, every setting should be applied immediately. + The accepted() signal will be emitted on close/hide regardless. + */ +class DLLEXPORT QToolbarTabDialog : public QObject +{ + Q_OBJECT +public: + QToolbarTabDialog(); + virtual ~QToolbarTabDialog(); + + /* + * If the given widget has a QSizePolicy of Fixed in either direction, the dialog will not be resizable in that + * direction. + */ + void addTab(QWidget* page, const QPixmap& icon, const QString& label, const QString& tooltip = QString()); + + void setCurrentIndex(int index); + + void show(); + void hide(); + +Q_SIGNALS: + void accepted(); + void rejected(); + +private: + QScopedPointer pimpl; + + friend class ::QToolbarTabDialogPrivate; +}; + +#endif // QTOOLBARTABWIDGET_H diff --git a/src/libtomahawk/thirdparty/Qocoa/qtoolbartabdialog_mac.mm b/src/libtomahawk/thirdparty/Qocoa/qtoolbartabdialog_mac.mm new file mode 100644 index 000000000..e36a1f15e --- /dev/null +++ b/src/libtomahawk/thirdparty/Qocoa/qtoolbartabdialog_mac.mm @@ -0,0 +1,448 @@ +/* + Copyright (C) 2012 by Leo Franchi + + 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 "qtoolbartabdialog.h" +#include "moc_qtoolbartabdialog.cpp" + +#include "qocoa_mac.h" + +#import +#import + +#include +#include +#include +#include +#include +#include + +struct ItemData { + QPixmap icon; + QString text, tooltip; + QMacNativeWidget* nativeWidget; + QWidget* page; +}; + + +namespace { + +static const int TOOLBAR_ITEM_WIDTH = 32; + +CGFloat ToolbarHeightForWindow(NSWindow *window) +{ + CGFloat toolbarHeight = 0.0f; + + NSToolbar *toolbar = toolbar = [window toolbar]; + + if(toolbar && [toolbar isVisible]) + { + NSRect windowFrame = [NSWindow contentRectForFrameRect:[window frame] + styleMask:[window styleMask]]; + toolbarHeight = NSHeight(windowFrame) - NSHeight([[window contentView] frame]); + } + + return toolbarHeight; +} + +}; + +@interface ToolbarDelegate : NSObject +{ + QToolbarTabDialogPrivate *pimpl; +} +// Internal +-(void)setPrivate:(QToolbarTabDialogPrivate*)withPimpl; + +// NSToolbarItem action +-(void)changePanes:(id)sender; + +// NSToolbarDelegate +-(NSToolbarItem *) toolbar: (NSToolbar *)toolbar itemForItemIdentifier: (NSString *) itemIdent willBeInsertedIntoToolbar:(BOOL) willBeInserted; +-(NSArray*) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar; +-(NSArray*) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar; +-(NSArray*) toolbarSelectableItemIdentifiers: (NSToolbar*)toolbar; + +// NSWindowDelegate +-(NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize; +-(void)windowWillClose:(NSNotification *)notification; +@end + +class QToolbarTabDialogPrivate { +public: + QToolbarTabDialogPrivate(QToolbarTabDialog* dialog) : q(dialog), + currentPane(NULL), + minimumWidthForToolbar(0) + { + } + + ~QToolbarTabDialogPrivate() { + // unset the delegate and toolbar from the window and manually release them + // otherwise, for some reason the old delegate is laying around when we + // create a new NSWindow + [[prefsWindow toolbar] setDelegate:NULL]; + [prefsWindow setToolbar:NULL]; + [prefsWindow release]; + [toolBar release]; + [toolBarDelegate release]; + } + + void calculateSize() { + NSRect windowFrame = [prefsWindow frame]; + + while ([[toolBar visibleItems] count] < [[toolBar items] count]) { + //Each toolbar item is 32x32; we expand by one toolbar item width repeatedly until they all fit + windowFrame.origin.x -= TOOLBAR_ITEM_WIDTH / 2; + windowFrame.size.width += TOOLBAR_ITEM_WIDTH / 2; + + [prefsWindow setFrame:windowFrame display:NO]; + [prefsWindow setMinSize: windowFrame.size]; + } + minimumWidthForToolbar = windowFrame.size.width; + } + + void showPaneWithIdentifier(NSString* ident) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + const QString identStr = toQString(ident); + Q_ASSERT(items.contains(identStr)); + if (!items.contains(identStr)) + return; + + QWidget* newWidget = items[identStr].nativeWidget; + Q_ASSERT(newWidget); + if (!newWidget) + return; + + QWidget* newPage = items[identStr].page; + Q_ASSERT(newPage); + if (!newPage) + return; + + // Clear first responder on window and set a temporary NSView on the window + // while we change the widget out underneath + [prefsWindow makeFirstResponder:nil]; + + NSView *tempView = [[NSView alloc] initWithFrame:[[prefsWindow contentView] frame]]; + [prefsWindow setContentView:tempView]; + [tempView release]; + + QSize sizeToUse = newPage->sizeHint().isNull() ? newPage->size() : newPage->sizeHint(); + + static const int spacing = 4; + + [prefsWindow setMinSize:NSMakeSize(sizeToUse.width(), sizeToUse.height())]; + + // Make room for the new view + NSRect newFrame = [prefsWindow frame]; + newFrame.size.height = sizeToUse.height() + ([prefsWindow frame].size.height - [[prefsWindow contentView] frame].size.height) + spacing; + newFrame.size.width = sizeToUse.width() + spacing; + + //Ensure the full toolbar still fits + if (newFrame.size.width < minimumWidthForToolbar) newFrame.size.width = minimumWidthForToolbar; + + // Preserve upper left point of window during resize. + newFrame.origin.y += ([[prefsWindow contentView] frame].size.height - sizeToUse.height()) - spacing; + + [prefsWindow setFrame:newFrame display:YES animate:YES]; + + [prefsWindow setContentView: [panes objectForKey:ident]]; + currentPane = ident; + + // Resize the Qt widget immediately as well + resizeCurrentPageToSize([[prefsWindow contentView] frame].size); + + NSSize minSize = [prefsWindow frame].size; + minSize.height -= ToolbarHeightForWindow(prefsWindow); + + [prefsWindow setMinSize:minSize]; + + BOOL canResize = YES; + NSSize maxSize = NSMakeSize(FLT_MAX, FLT_MAX); + + if (newPage->sizePolicy().horizontalPolicy() == QSizePolicy::Fixed) { + canResize = NO; + maxSize.width = minSize.width; + } + if (newPage->sizePolicy().verticalPolicy() == QSizePolicy::Fixed) { + canResize = NO; + maxSize.height = minSize.height; + } + + + [prefsWindow setMaxSize:maxSize]; + [prefsWindow setShowsResizeIndicator:canResize]; + + [prefsWindow setTitle:ident]; + + [pool drain]; + } + + void resizeCurrentPageToSize(NSSize frameSize) { + const QString curPane = toQString(currentPane); + if (items.contains(curPane) && items[curPane].nativeWidget) { + items[curPane].nativeWidget->resize(frameSize.width, frameSize.height); + } + } + + void emitAccepted() { + if (q.isNull()) + return; + + q.data()->accepted(); + } + + QWeakPointer q; + + NSWindow* prefsWindow; + ToolbarDelegate *toolBarDelegate; + QMap items; + + NSMutableDictionary *panes; + NSToolbar *toolBar; + NSString* currentPane; + + int minimumWidthForToolbar; +}; + + +@implementation ToolbarDelegate + +-(id) init { + if( self = [super init] ) + { + pimpl = nil; + } + + return self; +} + +-(void) setPrivate:(QToolbarTabDialogPrivate *)withPimpl +{ + pimpl = withPimpl; +} + +-(void)changePanes:(id)sender +{ + Q_UNUSED(sender); + if (!pimpl) + return; + + pimpl->showPaneWithIdentifier([pimpl->toolBar selectedItemIdentifier]); +} + +-(NSToolbarItem *) toolbar: (NSToolbar *)toolbar itemForItemIdentifier: (NSString *) itemIdent willBeInsertedIntoToolbar:(BOOL) willBeInserted +{ + Q_UNUSED(toolbar); + Q_UNUSED(willBeInserted); + if (!pimpl) + return nil; + + NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdent] autorelease]; + const QString identQStr = toQString(itemIdent); + if (pimpl->items.contains(identQStr)) + { + const ItemData& data = pimpl->items[identQStr]; + NSString* label = fromQString(data.text); + + [toolbarItem setLabel:label]; + [toolbarItem setPaletteLabel:label]; + + [toolbarItem setToolTip:fromQString(data.tooltip)]; + [toolbarItem setImage:fromQPixmap(data.icon)]; + + [toolbarItem setTarget: self]; + [toolbarItem setAction: @selector(changePanes:)]; + + } else { + toolbarItem = nil; + } + + return toolbarItem; +} + +-(NSArray*) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar +{ + Q_UNUSED(toolbar); + if (!pimpl) + return [NSArray array]; + + NSMutableArray* allowedItems = [[[NSMutableArray alloc] init] autorelease]; + + Q_FOREACH( const QString& identQStr, pimpl->items.keys()) + [allowedItems addObject:fromQString(identQStr)]; + + [allowedItems addObjectsFromArray:[NSArray arrayWithObjects:NSToolbarSeparatorItemIdentifier, + NSToolbarSpaceItemIdentifier, NSToolbarFlexibleSpaceItemIdentifier, + NSToolbarCustomizeToolbarItemIdentifier, nil] ]; + + return allowedItems; +} + + +-(NSArray*) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar +{ + Q_UNUSED(toolbar); + if (!pimpl) + return [NSArray array]; + + return [[[NSMutableArray alloc] initWithArray:[pimpl->panes allKeys]] autorelease]; + +} + + +-(NSArray*) toolbarSelectableItemIdentifiers: (NSToolbar*)toolbar +{ + Q_UNUSED(toolbar); + if (!pimpl) + return [NSArray array]; + + return [[[NSMutableArray alloc] initWithArray:[pimpl->panes allKeys]] autorelease]; +} + +-(NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize +{ + Q_UNUSED(sender); + if (!pimpl) + return frameSize; + + pimpl->resizeCurrentPageToSize(frameSize); + + return frameSize; +} + +-(void)windowWillClose:(NSNotification *)notification +{ + Q_UNUSED(notification); + + pimpl->emitAccepted(); +} +@end + +QToolbarTabDialog::QToolbarTabDialog() : + QObject(0), + pimpl(new QToolbarTabDialogPrivate(this)) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + pimpl->panes = [[NSMutableDictionary alloc] init]; + + static const int defaultWidth = 350; + static const int defaultHeight = 200; + pimpl->prefsWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, defaultWidth, defaultHeight) + styleMask:NSClosableWindowMask | NSResizableWindowMask | NSTitledWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + + [pimpl->prefsWindow setReleasedWhenClosed:NO]; + [pimpl->prefsWindow setTitle:@"Preferences"]; + + // identifier is some app-unique string, since all toolbars in an app share state. make this unique to this app's preferences window + pimpl->toolBar = [[NSToolbar alloc] initWithIdentifier:[NSString stringWithFormat:@"%@.prefspanel.toolbar", fromQString(QCoreApplication::instance()->applicationName())]]; + [pimpl->toolBar setAllowsUserCustomization: NO]; + [pimpl->toolBar setAutosavesConfiguration: NO]; + [pimpl->toolBar setDisplayMode: NSToolbarDisplayModeIconAndLabel]; + + pimpl->toolBarDelegate = [[ToolbarDelegate alloc] init]; + [pimpl->toolBarDelegate setPrivate:pimpl.data()]; + + [pimpl->prefsWindow setDelegate:pimpl->toolBarDelegate]; + [pimpl->toolBar setDelegate:pimpl->toolBarDelegate]; + + [pimpl->prefsWindow setToolbar:pimpl->toolBar]; + + [pool drain]; +} + +QToolbarTabDialog::~QToolbarTabDialog() +{ +} + +void QToolbarTabDialog::addTab(QWidget* page, const QPixmap& icon, const QString& label, const QString& tooltip) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSString* identifier = fromQString(label); + + QMacNativeWidget* nativeWidget = new QMacNativeWidget; + nativeWidget->move(0, 0); + nativeWidget->setPalette(page->palette()); + nativeWidget->setAutoFillBackground(true); + + QVBoxLayout* l = new QVBoxLayout; + l->setContentsMargins(2, 2, 2, 2); + l->setSpacing(0); + page->setAttribute(Qt::WA_LayoutUsesWidgetRect); + l->addWidget(page); + nativeWidget->setLayout(l); + + NSView *nativeView = reinterpret_cast(nativeWidget->winId()); + [nativeView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + [nativeView setAutoresizesSubviews:YES]; + + nativeWidget->show(); + + ItemData data; + data.icon = icon; + data.text = label; + data.tooltip = tooltip; + data.nativeWidget = nativeWidget; + data.page = page; + pimpl->items.insert(label, data); + + [pimpl->panes setObject:nativeView forKey:identifier]; + + pimpl->showPaneWithIdentifier(identifier); + + [pimpl->toolBar insertItemWithItemIdentifier:identifier atIndex:[[pimpl->toolBar items] count]]; + [pimpl->toolBar setSelectedItemIdentifier:identifier]; + [[pimpl->prefsWindow standardWindowButton:NSWindowZoomButton] setEnabled:NO]; + + pimpl->calculateSize(); + [pool drain]; +} + + +void QToolbarTabDialog::setCurrentIndex(int index) +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + [pimpl->toolBar setSelectedItemIdentifier:[[[pimpl->toolBar items] objectAtIndex:index] itemIdentifier]]; + pimpl->showPaneWithIdentifier([[[pimpl->toolBar items] objectAtIndex:index] itemIdentifier]); +} + +void QToolbarTabDialog::show() +{ + [pimpl->prefsWindow makeKeyAndOrderFront:nil]; +} + +void QToolbarTabDialog::hide() +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + [pimpl->prefsWindow close]; + emit accepted(); +} + diff --git a/src/libtomahawk/thirdparty/Qocoa/qtoolbartabdialog_nonmac.cpp b/src/libtomahawk/thirdparty/Qocoa/qtoolbartabdialog_nonmac.cpp new file mode 100644 index 000000000..08b998b4c --- /dev/null +++ b/src/libtomahawk/thirdparty/Qocoa/qtoolbartabdialog_nonmac.cpp @@ -0,0 +1,167 @@ +#include "qtoolbartabdialog.h" + +#include +#include +#include +#include +#include +#include +#include + +class QToolbarTabDialogPrivate : public QObject { + Q_OBJECT +public: + QToolbarTabDialogPrivate(QToolbarTabDialog* qq) : q(qq), layout(0), toolbar(0), rightSpacer(0), stack(0), separator(0), buttons(0), actionGroup(0) {} + +public slots: + void actionTriggered(QAction* action) { + if (dialog.isNull()) + return; + + const int idx = toolbar->actions().indexOf(action); + Q_ASSERT(idx > -1); + if (idx < 0) + return; + + stack->setCurrentIndex(idx); + } + + void accepted() { + Q_ASSERT(!dialog.isNull()); + Q_ASSERT(!q.isNull()); + + dialog.data()->hide(); + emit q.data()->accepted(); + } + + void rejected() { + Q_ASSERT(!dialog.isNull()); + Q_ASSERT(!q.isNull()); + + dialog.data()->hide(); + emit q.data()->rejected(); + } + +public: + QWeakPointer dialog; + QWeakPointer q; + + QVBoxLayout* layout; + QToolBar* toolbar; + QAction* rightSpacer; + QStackedWidget* stack; + QFrame* separator; + QDialogButtonBox* buttons; + QActionGroup* actionGroup; + +}; + +QToolbarTabDialog::QToolbarTabDialog() : + QObject(0), + pimpl(new QToolbarTabDialogPrivate(this)) +{ + pimpl->dialog = new QDialog; + pimpl->dialog.data()->setModal(true); + + pimpl->toolbar = new QToolBar(pimpl->dialog.data()); + pimpl->toolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); + + pimpl->stack = new QStackedWidget(pimpl->dialog.data()); + + pimpl->separator = new QFrame(pimpl->dialog.data()); + pimpl->separator->setFrameShape(QFrame::HLine); + pimpl->separator->setFrameShadow(QFrame::Sunken); + + pimpl->actionGroup = new QActionGroup(pimpl->dialog.data()); + + connect(pimpl->toolbar, SIGNAL(actionTriggered(QAction*)), pimpl.data(), SLOT(actionTriggered(QAction*))); + + pimpl->buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, pimpl->dialog.data()); + connect(pimpl->buttons, SIGNAL(accepted()), pimpl->dialog.data(), SLOT(accept())); + connect(pimpl->buttons, SIGNAL(rejected()), pimpl->dialog.data(), SLOT(reject())); + + connect(pimpl->dialog.data(), SIGNAL(accepted()), pimpl.data(), SLOT(accepted())); + connect(pimpl->dialog.data(), SIGNAL(rejected()), pimpl.data(), SLOT(rejected())); + + QWidget* leftSpacer = new QWidget(pimpl->toolbar); + leftSpacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + QWidget* rightSpacer = new QWidget(pimpl->toolbar); + rightSpacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + + pimpl->toolbar->addWidget(leftSpacer); + pimpl->rightSpacer = pimpl->toolbar->addWidget(rightSpacer); + + pimpl->layout = new QVBoxLayout; + pimpl->layout->addWidget(pimpl->toolbar); + pimpl->layout->addWidget(pimpl->separator); + pimpl->layout->addWidget(pimpl->stack); + pimpl->layout->addWidget(pimpl->buttons); + pimpl->dialog.data()->setLayout(pimpl->layout); +} + +QToolbarTabDialog::~QToolbarTabDialog() +{ + if (pimpl && !pimpl->dialog.isNull()) { + delete pimpl->dialog.data(); + } +} + +void QToolbarTabDialog::addTab(QWidget* page, const QPixmap& icon, const QString& label, const QString& tooltip) +{ + Q_ASSERT(pimpl); + if (!pimpl) + return; + + pimpl->toolbar->removeAction(pimpl->rightSpacer); + + QAction* action = new QAction(icon, label, pimpl->toolbar); + action->setCheckable(true); + action->setToolTip(tooltip); + + pimpl->actionGroup->addAction(action); + + pimpl->toolbar->addAction(action); + pimpl->stack->addWidget(page); + + pimpl->toolbar->addAction(pimpl->rightSpacer); +} + +void QToolbarTabDialog::setCurrentIndex(int index) +{ + Q_ASSERT(pimpl); + if (!pimpl || pimpl->dialog.isNull()) + return; + + + Q_ASSERT(index < pimpl->toolbar->actions().length()); + Q_ASSERT(index < pimpl->stack->count()); + if (index < 0 || index > pimpl->toolbar->actions().length()) + return; + if (index > pimpl->stack->count()) + return; + + if (pimpl->stack->currentIndex() != index) + pimpl->stack->setCurrentIndex(index); +} + +void QToolbarTabDialog::show() +{ + Q_ASSERT(pimpl); + Q_ASSERT(!pimpl->dialog.isNull()); + if (!pimpl || pimpl->dialog.isNull()) + return; + + pimpl->dialog.data()->show(); +} + +void QToolbarTabDialog::hide() +{ + Q_ASSERT(pimpl); + Q_ASSERT(!pimpl->dialog.isNull()); + if (!pimpl || pimpl->dialog.isNull()) + return; + + pimpl->dialog.data()->hide(); +} + +#include "moc_qtoolbartabdialog_nonmac.cpp"