diff --git a/core/audex.h b/core/audex.h index d8ba20e..fab6b6e 100644 --- a/core/audex.h +++ b/core/audex.h @@ -1,290 +1,290 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef AUDEX_HEADER #define AUDEX_HEADER #include #include #include #include #include #include #include "models/cddamodel.h" #include "models/profilemodel.h" #include "utils/cddaextractthread.h" #include "utils/cuesheetwriter.h" #include "utils/discidcalculator.h" #include "utils/encoderwrapper.h" #include "utils/hashlist.h" #include "utils/parameters.h" #include "utils/patternparser.h" #include "utils/playlist.h" #include "utils/tmpdir.h" #include "utils/upload.h" #include "utils/wavefilewriter.h" #include "preferences.h" class AudexJob : public QObject { Q_OBJECT public: - explicit AudexJob(QObject *parent = 0) + explicit AudexJob(QObject *parent = nullptr) : QObject(parent) { source_filename = ""; target_filename = ""; _trackno = 0; } ~AudexJob() override { } void setSourceFilename(const QString &n) { source_filename = n; } QString sourceFilename() const { return source_filename; } void setTargetFilename(const QString &n) { target_filename = n; } QString targetFilename() const { return target_filename; } void setTrackNo(const int t) { _trackno = t; } int trackNo() const { return _trackno; } private: QString source_filename; QString target_filename; int _trackno; }; class AudexJobs : public QObject { Q_OBJECT public: - explicit AudexJobs(QObject *parent = 0) + explicit AudexJobs(QObject *parent = nullptr) : QObject(parent) { job_in_progress = false; } ~AudexJobs() override { for (int i = 0; i < cache.count(); i++) { // make really sure all files are away QFile file(cache.at(i)->sourceFilename()); if (file.exists()) file.remove(); delete cache.at(i); } } AudexJob *orderJob() { if (job_queue.isEmpty()) { - return NULL; + return nullptr; } else { job_in_progress = true; return job_queue.dequeue(); } } void reportJobFinished() { job_in_progress = false; } bool jobInProgress() { return job_in_progress; } bool pendingJobs() { return (job_queue.count() > 0); } public slots: void addNewJob(const QString &sourceFilename, const QString &targetFilename, const int trackno) { AudexJob *j = new AudexJob(); j->setSourceFilename(sourceFilename); j->setTargetFilename(targetFilename); j->setTrackNo(trackno); job_queue.enqueue(j); cache.append(j); emit newJobAvailable(); } signals: void newJobAvailable(); private: QQueue job_queue; QList cache; bool job_in_progress; }; class Audex : public QObject { Q_OBJECT public: Audex(QWidget *parent, ProfileModel *profile_model, CDDAModel *cdda_model); ~Audex() override; bool prepare(); public slots: void start(); void cancel(); const QStringList &extractProtocol(); const QStringList &encoderProtocol(); private slots: void start_extract(); void finish_extract(); void start_encode(); void finish_encode(); void calculate_speed_extract(); void calculate_speed_encode(); void progress_extract(int percent_of_track, int sector, int overall_sectors_read); void progress_encode(int percent); void write_to_wave(const QByteArray &data); void slot_error(const QString &message, const QString &details = QString()); void slot_warning(const QString &message); void slot_info(const QString &message); void check_if_thread_still_running(); signals: void changedExtractTrack(int no, int total, const QString &artist, const QString &title); void changedEncodeTrack(int no, int total, const QString &filename); void progressExtractTrack(int percent); void progressExtractOverall(int percent); void progressEncodeTrack(int percent); void progressEncodeOverall(int percent); void speedExtract(double times); void speedEncode(double times); void finished(bool successful); void timeout(); void error(const QString &message, const QString &details = QString()); void warning(const QString &message); void info(const QString &message); private: QWidget *parent; ProfileModel *profile_model; CDDAModel *cdda_model; EncoderWrapper *encoder_wrapper; CDDAExtractThread *cdda_extract_thread; AudexJobs *jobs; WaveFileWriter *wave_file_writer; TmpDir *tmp_dir; QString p_profile_name; QString p_suffix; bool p_single_file; bool construct_target_filename(QString &targetFilename, int trackno, int cdno, int nooftracks, int gindex, const QString &artist, const QString &title, const QString &tartist, const QString &ttitle, const QString &date, const QString &genre, const QString &ext, const QString &basepath, bool fat_compatible, bool replacespaceswithunderscores, bool _2digitstracknum, bool overwrite_existing_files, bool is_first_track); bool construct_target_filename_for_singlefile(QString &targetFilename, int cdno, int nooftracks, const QString &artist, const QString &title, const QString &date, const QString &genre, const QString &ext, const QString &basepath, bool overwrite_existing_files); bool check(); QString tmp_path; QString target_dir; bool _finished; bool _finished_successful; void request_finish(bool successful); void execute_finish(); int process_counter; bool timeout_done; int timeout_counter; /*PROCESS 1: EXTRACTING*/ QString ex_track_source_filename; QString ex_track_target_filename; int ex_track_index; int ex_track_count; QTimer *timer_extract; int current_sector; int last_measuring_point_sector; int overall_frames; /*PROCESS 2: ENCODING*/ QString en_track_filename; QString en_track_target_filename; int en_track_index; int en_track_count; QTimer *timer_encode; int current_encoder_percent; int last_measuring_point_encoder_percent; bool p_prepare_dir(QString &filename, const QString &targetDirIfRelative, const bool overwrite = false); bool p_mkdir(const QString &absoluteFilePath); qreal p_size_of_all_files(const QStringList &filenames) const; }; #endif diff --git a/dialogs/cddaheaderdatadialog.h b/dialogs/cddaheaderdatadialog.h index 6f64e63..fc330bd 100644 --- a/dialogs/cddaheaderdatadialog.h +++ b/dialogs/cddaheaderdatadialog.h @@ -1,56 +1,56 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CDDAHEADERDATADIALOG_H #define CDDAHEADERDATADIALOG_H #include #include #include #include #include "models/cddamodel.h" #include "utils/discidcalculator.h" #include "ui_cddaheaderdatawidgetUI.h" class CDDAHeaderDataDialog : public QDialog { Q_OBJECT public: - explicit CDDAHeaderDataDialog(CDDAModel *cddaModel, QWidget *parent = 0); + explicit CDDAHeaderDataDialog(CDDAModel *cddaModel, QWidget *parent = nullptr); ~CDDAHeaderDataDialog() override; private slots: void save(); void trigger_changed(); void enable_checkbox_multicd(bool enabled); void slotAccepted(); void slotApplied(); private: Ui::CDDAHeaderDataWidgetUI ui; CDDAModel *cdda_model; QPushButton *okButton; QPushButton *applyButton; }; #endif diff --git a/dialogs/commandwizarddialog.h b/dialogs/commandwizarddialog.h index 09a830c..65758ee 100644 --- a/dialogs/commandwizarddialog.h +++ b/dialogs/commandwizarddialog.h @@ -1,75 +1,75 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COMMANDWIZARDDIALOG_H #define COMMANDWIZARDDIALOG_H #include #include #include #include #include "utils/patternparser.h" #include "ui_commandwizardwidgetUI.h" class CommandWizardDialog : public QDialog { Q_OBJECT public: - explicit CommandWizardDialog(const QString &command, QWidget *parent = 0); + explicit CommandWizardDialog(const QString &command, QWidget *parent = nullptr); ~CommandWizardDialog() override; QString command; private slots: void trigger_changed(); void about_commandline_schemes(); void about_parameters(); void insAlbumArtist(); void insAlbumTitle(); void insTrackArtist(); void insTrackTitle(); void insTrackNo(); void insCDNo(); void insDate(); void insGenre(); void insCoverFile(); void insNoOfTracks(); void insInFile(); void insOutFile(); void update_example(); void slotAccepted(); void slotApplied(); private: Ui::CommandWizardWidgetUI ui; bool save(); QPushButton *okButton; QPushButton *applyButton; }; #endif diff --git a/dialogs/coverbrowserdialog.h b/dialogs/coverbrowserdialog.h index 62df21e..c4f8bcd 100644 --- a/dialogs/coverbrowserdialog.h +++ b/dialogs/coverbrowserdialog.h @@ -1,81 +1,81 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COVERBROWSERDIALOG_H #define COVERBROWSERDIALOG_H #include #include #include #include #include #include "preferences.h" #include "dialogs/errordialog.h" #include "utils/coverfetcher.h" #include "ui_coverbrowserwidgetUI.h" class CoverBrowserDialog : public QDialog { Q_OBJECT public: - explicit CoverBrowserDialog(QWidget *parent = 0); + explicit CoverBrowserDialog(QWidget *parent = nullptr); ~CoverBrowserDialog() override; inline int count() { return cover_fetcher.count(); } public slots: void fetchThumbnails(const QString &searchstring, const int fetchCount = 0); void startFetchCover(const int no); signals: void coverFetched(const QByteArray &cover); void allCoverThumbnailsFetched(); void nothingFetched(); private slots: void select_this(QListWidgetItem *item); void enable_select_button(); void add_item(const QByteArray &cover, const QString &caption, int no); void all_fetched(); void nothing_fetched(); void cover_fetched(const QByteArray &cover); void error(const QString &description, const QString &solution); void slotAccepted(); private: Ui::CoverBrowserWidgetUI ui; CoverFetcher cover_fetcher; QPushButton *okButton; void setup(); }; #endif diff --git a/dialogs/extractingprogressdialog.h b/dialogs/extractingprogressdialog.h index 2a8d509..fc662a5 100644 --- a/dialogs/extractingprogressdialog.h +++ b/dialogs/extractingprogressdialog.h @@ -1,111 +1,111 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef EXTRACTINGPROGRESSDIALOG_H #define EXTRACTINGPROGRESSDIALOG_H #include #include #include #include #include #include #include #include #include #include #include #include "core/audex.h" #include "models/cddamodel.h" #include "models/profilemodel.h" #include "protocoldialog.h" #include "ui_extractingprogresswidgetUI.h" class ExtractingProgressDialog : public QDialog { Q_OBJECT public: - ExtractingProgressDialog(ProfileModel *profile_model, CDDAModel *cdda_model, QWidget *parent = 0); + ExtractingProgressDialog(ProfileModel *profile_model, CDDAModel *cdda_model, QWidget *parent = nullptr); ~ExtractingProgressDialog() override; public slots: int exec() override; private slots: void toggle_details(); void cancel(); void slotCancel(); void slotClose(); void slotEncoderProtocol(); void slotExtractProtocol(); void show_changed_extract_track(int no, int total, const QString &artist, const QString &title); void show_changed_encode_track(int no, int total, const QString &filename); void show_progress_extract_track(int percent); void show_progress_extract_overall(int percent); void show_progress_encode_track(int percent); void show_progress_encode_overall(int percent); void show_speed_encode(double speed); void show_speed_extract(double speed); void conclusion(bool successful); void show_info(const QString &message); void show_warning(const QString &message); void show_error(const QString &message, const QString &details); void ask_timeout(); private: QVBoxLayout *mainLayout; QDialogButtonBox *buttonBox; QPushButton *cancelButton; void calc_overall_progress(); void open_encoder_protocol_dialog(); void open_extract_protocol_dialog(); void update_unity(); private: Ui::ExtractingProgressWidgetUI ui; Audex *audex; ProfileModel *profile_model; CDDAModel *cdda_model; bool finished; bool progressbar_np_flag; int current_encode_overall; int current_extract_overall; unsigned int current_track; bool p_single_file; QDBusMessage unity_message; }; #endif diff --git a/dialogs/patternwizarddialog.h b/dialogs/patternwizarddialog.h index 20139bc..b52ae5c 100644 --- a/dialogs/patternwizarddialog.h +++ b/dialogs/patternwizarddialog.h @@ -1,72 +1,72 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PATTERNWIZARDDIALOG_H #define PATTERNWIZARDDIALOG_H #include #include #include #include #include "utils/patternparser.h" #include "ui_patternwizardwidgetUI.h" class PatternWizardDialog : public QDialog { Q_OBJECT public: - explicit PatternWizardDialog(const QString &pattern, QWidget *parent = 0); + explicit PatternWizardDialog(const QString &pattern, QWidget *parent = nullptr); ~PatternWizardDialog() override; QString pattern; private slots: void trigger_changed(); void about_filename_schemes(); void about_parameters(); void insAlbumArtist(); void insAlbumTitle(); void insTrackArtist(); void insTrackTitle(); void insTrackNo(); void insCDNo(); void insDate(); void insGenre(); void insSuffix(); void insNoOfTracks(); void update_example(); void slotAccepted(); void slotApplied(); private: Ui::PatternWizardWidgetUI ui; bool save(); QPushButton *applyButton; }; #endif diff --git a/dialogs/profiledatacoverdialog.h b/dialogs/profiledatacoverdialog.h index abb90da..6f3217a 100644 --- a/dialogs/profiledatacoverdialog.h +++ b/dialogs/profiledatacoverdialog.h @@ -1,61 +1,61 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROFILEDATACOVERDIALOG_H #define PROFILEDATACOVERDIALOG_H #include #include #include #include "simplepatternwizarddialog.h" #include "ui_profiledatacoverwidgetUI.h" class ProfileDataCoverDialog : public QDialog { Q_OBJECT public: - ProfileDataCoverDialog(const bool scale, const QSize &size, const QString &format, const QString &pattern, QWidget *parent = 0); + ProfileDataCoverDialog(const bool scale, const QSize &size, const QString &format, const QString &pattern, QWidget *parent = nullptr); ~ProfileDataCoverDialog() override; bool scale; QSize size; QString format; QString pattern; protected slots: void pattern_wizard(); private slots: void trigger_changed(); void enable_scale(bool enabled); void slotAccepted(); void slotApplied(); private: Ui::ProfileDataCoverWidgetUI ui; QPushButton *applyButton; bool save(); }; #endif diff --git a/dialogs/profiledatacuesheetdialog.h b/dialogs/profiledatacuesheetdialog.h index 3261b46..6d1cc7d 100644 --- a/dialogs/profiledatacuesheetdialog.h +++ b/dialogs/profiledatacuesheetdialog.h @@ -1,57 +1,57 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROFILEDATACUESHEETDIALOG_H #define PROFILEDATACUESHEETDIALOG_H #include #include #include #include "simplepatternwizarddialog.h" #include "ui_profiledatacuesheetwidgetUI.h" class ProfileDataCueSheetDialog : public QDialog { Q_OBJECT public: - explicit ProfileDataCueSheetDialog(const QString &pattern, QWidget *parent = 0); + explicit ProfileDataCueSheetDialog(const QString &pattern, QWidget *parent = nullptr); ~ProfileDataCueSheetDialog() override; QString pattern; protected slots: void pattern_wizard(); private slots: void trigger_changed(); void slotAccepted(); void slotApplied(); private: Ui::ProfileDataCueSheetWidgetUI ui; QPushButton *applyButton; bool save(); }; #endif diff --git a/dialogs/profiledatadialog.h b/dialogs/profiledatadialog.h index 506abc5..6f24f58 100644 --- a/dialogs/profiledatadialog.h +++ b/dialogs/profiledatadialog.h @@ -1,133 +1,133 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROFILEDATADIALOG_H #define PROFILEDATADIALOG_H #include #include #include #include #include "models/profilemodel.h" #include "utils/encoderassistant.h" #include "widgets/customwidget.h" #include "widgets/faacwidget.h" #include "widgets/flacwidget.h" #include "widgets/lamewidget.h" #include "widgets/oggencwidget.h" #include "widgets/wavewidget.h" #include "dialogs/errordialog.h" #include "dialogs/patternwizarddialog.h" #include "dialogs/profiledatacoverdialog.h" #include "dialogs/profiledatacuesheetdialog.h" #include "dialogs/profiledatahashlistdialog.h" #include "dialogs/profiledatainfodialog.h" #include "dialogs/profiledataplaylistdialog.h" #include "dialogs/profiledatasinglefiledialog.h" #include "ui_profiledatawidgetUI.h" class ProfileDataDialog : public QDialog { Q_OBJECT public: - ProfileDataDialog(ProfileModel *profileModel, const int profileRow, QWidget *parent = 0); + ProfileDataDialog(ProfileModel *profileModel, const int profileRow, QWidget *parent = nullptr); ~ProfileDataDialog() override; private slots: void set_encoder(const int encoder); void set_encoder_by_combobox(const int index); void trigger_changed(); void enable_settings_cover(bool enabled); void enable_settings_playlist(bool enabled); void enable_settings_info(bool enabled); void enable_settings_hashlist(bool enabled); void enable_settings_cuesheet(bool enabled); void enable_settings_singlefile(bool enabled); void disable_playlist(bool disabled); void enable_filenames(bool enabled); void disable_filenames(bool disabled); void pattern_wizard(); void cover_settings(); void playlist_settings(); void info_settings(); void hashlist_settings(); void cuesheet_settings(); void singlefile_settings(); void slotAccepted(); void slotApplied(); private: Ui::ProfileDataWidgetUI ui; ProfileModel *profile_model; QPushButton *applyButton; int profile_row; lameWidget *lame_widget; Parameters lame_parameters; oggencWidget *oggenc_widget; Parameters oggenc_parameters; flacWidget *flac_widget; Parameters flac_parameters; faacWidget *faac_widget; Parameters faac_parameters; waveWidget *wave_widget; Parameters wave_parameters; customWidget *custom_widget; Parameters custom_parameters; void set_encoder_widget(const EncoderAssistant::Encoder encoder); bool pdcd_scale; QSize pdcd_size; QString pdcd_format; QString pdcd_pattern; QString pdpd_format; QString pdpd_pattern; bool pdpd_abs_file_path; bool pdpd_utf8; QStringList pdid_text; QString pdid_pattern; QString pdid_suffix; QString pdhd_format; QString pdhd_pattern; QString pdud_pattern; QString pdsd_pattern; bool save(); Error error; }; #endif diff --git a/dialogs/profiledatahashlistdialog.h b/dialogs/profiledatahashlistdialog.h index 4e7be09..b73fee1 100644 --- a/dialogs/profiledatahashlistdialog.h +++ b/dialogs/profiledatahashlistdialog.h @@ -1,58 +1,58 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROFILEDATAHASHLISTDIALOG_H #define PROFILEDATAHASHLISTDIALOG_H #include #include #include #include "simplepatternwizarddialog.h" #include "ui_profiledatahashlistwidgetUI.h" class ProfileDataHashlistDialog : public QDialog { Q_OBJECT public: - ProfileDataHashlistDialog(const QString &pattern, const QString &format, QWidget *parent = 0); + ProfileDataHashlistDialog(const QString &pattern, const QString &format, QWidget *parent = nullptr); ~ProfileDataHashlistDialog() override; QString format; QString pattern; protected slots: void pattern_wizard(); private slots: void trigger_changed(); void slotAccepted(); void slotApplied(); private: Ui::ProfileDataHashlistWidgetUI ui; QPushButton *applyButton; bool save(); }; #endif diff --git a/dialogs/profiledatainfodialog.h b/dialogs/profiledatainfodialog.h index 003c008..ada4588 100644 --- a/dialogs/profiledatainfodialog.h +++ b/dialogs/profiledatainfodialog.h @@ -1,67 +1,67 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROFILEDATAINFODIALOG_H #define PROFILEDATAINFODIALOG_H #include #include #include #include #include #include "simplepatternwizarddialog.h" #include "ui_profiledatainfowidgetUI.h" class ProfileDataInfoDialog : public QDialog { Q_OBJECT public: - ProfileDataInfoDialog(const QStringList &text, const QString &pattern, const QString &suffix, QWidget *parent = 0); + ProfileDataInfoDialog(const QStringList &text, const QString &pattern, const QString &suffix, QWidget *parent = nullptr); ~ProfileDataInfoDialog() override; QStringList text; QString pattern; QString suffix; protected slots: void pattern_wizard(); private slots: void trigger_changed(); void about_variables(); void load_text(); void save_text(); void slotAccepted(); void slotApplied(); private: Ui::ProfileDataInfoWidgetUI ui; QVBoxLayout *mainLayout; QPushButton *applyButton; bool save(); }; #endif diff --git a/dialogs/profiledataplaylistdialog.h b/dialogs/profiledataplaylistdialog.h index 7f4991d..c8b5ec3 100644 --- a/dialogs/profiledataplaylistdialog.h +++ b/dialogs/profiledataplaylistdialog.h @@ -1,62 +1,62 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROFILEDATAPLAYLISTDIALOG_H #define PROFILEDATAPLAYLISTDIALOG_H #include #include #include #include "simplepatternwizarddialog.h" #include "ui_profiledataplaylistwidgetUI.h" class ProfileDataPlaylistDialog : public QDialog { Q_OBJECT public: - ProfileDataPlaylistDialog(const QString &format, const QString &pattern, const bool absFilePath, const bool utf8, QWidget *parent = 0); + ProfileDataPlaylistDialog(const QString &format, const QString &pattern, const bool absFilePath, const bool utf8, QWidget *parent = nullptr); ~ProfileDataPlaylistDialog() override; QString format; QString pattern; bool absFilePath; bool utf8; protected slots: void pattern_wizard(); private slots: void trigger_changed(); void enable_abs_file_path(bool enabled); void enable_utf8(bool enabled); void slotAccepted(); void slotApplied(); private: Ui::ProfileDataPlaylistWidgetUI ui; QPushButton *applyButton; bool save(); }; #endif diff --git a/dialogs/profiledatasinglefiledialog.h b/dialogs/profiledatasinglefiledialog.h index eb3e212..047a6e8 100644 --- a/dialogs/profiledatasinglefiledialog.h +++ b/dialogs/profiledatasinglefiledialog.h @@ -1,57 +1,57 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROFILEDATASINGLEFILEDIALOG_H #define PROFILEDATASINGLEFILEDIALOG_H #include #include #include #include "simplepatternwizarddialog.h" #include "ui_profiledatasinglefilewidgetUI.h" class ProfileDataSingleFileDialog : public QDialog { Q_OBJECT public: - explicit ProfileDataSingleFileDialog(const QString &pattern, QWidget *parent = 0); + explicit ProfileDataSingleFileDialog(const QString &pattern, QWidget *parent = nullptr); ~ProfileDataSingleFileDialog() override; QString pattern; protected slots: void pattern_wizard(); private slots: void trigger_changed(); void slotAccepted(); void slotApplied(); private: Ui::ProfileDataSingleFileWidgetUI ui; QPushButton *applyButton; bool save(); }; #endif diff --git a/dialogs/protocoldialog.h b/dialogs/protocoldialog.h index 08df6a1..5737c1e 100644 --- a/dialogs/protocoldialog.h +++ b/dialogs/protocoldialog.h @@ -1,49 +1,49 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROTOCOLDIALOG_H #define PROTOCOLDIALOG_H #include #include #include #include "ui_protocolwidgetUI.h" class ProtocolDialog : public QDialog { Q_OBJECT public: - ProtocolDialog(const QStringList &protocol, const QString &title, QWidget *parent = 0); + ProtocolDialog(const QStringList &protocol, const QString &title, QWidget *parent = nullptr); ~ProtocolDialog() override; private slots: void slotSaveProtocol(); void slotClosed(); void save(); private: Ui::ProtocolWidgetUI ui; QStringList protocol; QString title; }; #endif diff --git a/dialogs/simplepatternwizarddialog.h b/dialogs/simplepatternwizarddialog.h index 207069e..6741b7f 100644 --- a/dialogs/simplepatternwizarddialog.h +++ b/dialogs/simplepatternwizarddialog.h @@ -1,68 +1,68 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SIMPLEPATTERNWIZARDDIALOG_H #define SIMPLEPATTERNWIZARDDIALOG_H #include #include #include #include "utils/patternparser.h" #include "ui_simplepatternwizardwidgetUI.h" class SimplePatternWizardDialog : public QDialog { Q_OBJECT public: - SimplePatternWizardDialog(const QString &pattern, const QString &suffix, QWidget *parent = 0); + SimplePatternWizardDialog(const QString &pattern, const QString &suffix, QWidget *parent = nullptr); ~SimplePatternWizardDialog() override; QString pattern; private slots: void trigger_changed(); void about_schemes(); void about_parameters(); void insAlbumArtist(); void insAlbumTitle(); void insCDNo(); void insDate(); void insGenre(); void insSuffix(); void insNoOfTracks(); void update_example(); void slotAccepted(); void slotApplied(); private: Ui::SimplePatternWizardWidgetUI ui; QString suffix; QPushButton *applyButton; bool save(); }; #endif diff --git a/main.cpp b/main.cpp index 6be05da..62019f1 100644 --- a/main.cpp +++ b/main.cpp @@ -1,74 +1,74 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include "config.h" #include "mainwindow.h" #include int main(int argc, char *argv[]) { Kdelibs4ConfigMigrator migrator(QStringLiteral("audex")); migrator.setConfigFiles(QStringList() << QStringLiteral("audexrc")); migrator.migrate(); QApplication app(argc, argv); app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); KCrash::initialize(); KLocalizedString::setApplicationDomain("audex"); KAboutData aboutData("audex", i18n("Audex"), AUDEX_VERSION); aboutData.setShortDescription(i18n("KDE CDDA Extractor")); aboutData.setLicense(KAboutLicense::GPL); aboutData.setCopyrightStatement(i18n("Copyright © 2007–2015 by Marco Nelles")); aboutData.setHomepage("https://userbase.kde.org/Audex"); aboutData.setBugAddress("audex@maniatek.com"); aboutData.addAuthor(i18n("Marco Nelles"), i18n("Current maintainer, main developer"), "marco@maniatek.de"); - aboutData.addCredit(i18n("Craig Drummond"), i18n("GUI improvements, development"), 0, ""); - aboutData.addCredit(i18n("Elson"), i18n("development"), 0, ""); - aboutData.addCredit(i18n("credativ GmbH"), i18n("Special thanks to credativ GmbH (Germany) for support"), 0, "http://www.credativ.com/"); - aboutData.addCredit(i18n("freedb.org"), i18n("Special thanks to freedb.org for providing a free CDDB-like CD database"), 0, "http://freedb.org"); - aboutData.addCredit(i18n("Xiph.Org Foundation"), i18n("Special thanks to Xiph.Org Foundation for providing compact disc ripper"), 0, "http://www.xiph.org/paranoia/index.html"); + aboutData.addCredit(i18n("Craig Drummond"), i18n("GUI improvements, development"), nullptr, ""); + aboutData.addCredit(i18n("Elson"), i18n("development"), nullptr, ""); + aboutData.addCredit(i18n("credativ GmbH"), i18n("Special thanks to credativ GmbH (Germany) for support"), nullptr, "http://www.credativ.com/"); + aboutData.addCredit(i18n("freedb.org"), i18n("Special thanks to freedb.org for providing a free CDDB-like CD database"), nullptr, "http://freedb.org"); + aboutData.addCredit(i18n("Xiph.Org Foundation"), i18n("Special thanks to Xiph.Org Foundation for providing compact disc ripper"), nullptr, "http://www.xiph.org/paranoia/index.html"); aboutData.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails")); aboutData.setOrganizationDomain(QByteArray("kde.org")); aboutData.setDesktopFileName(QStringLiteral("org.kde.audex")); app.setWindowIcon(QIcon::fromTheme(QStringLiteral("audex"))); QCommandLineParser parser; KAboutData::setApplicationData(aboutData); parser.addVersionOption(); parser.addHelpOption(); aboutData.setupCommandLine(&parser); parser.process(app); aboutData.processCommandLine(&parser); MainWindow *window = new MainWindow(); window->show(); return app.exec(); } diff --git a/mainwindow.h b/mainwindow.h index 0089a01..3f0058d 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1,135 +1,135 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "utils/cuesheetwriter.h" #include "utils/error.h" #include "models/cddamodel.h" #include "models/profilemodel.h" #include "preferences.h" #include "widgets/cddaheaderwidget.h" #include "widgets/devicewidget.h" #include "widgets/generalsettingswidget.h" #include "widgets/profilewidget.h" #include "widgets/remoteserversettingswidget.h" #include "dialogs/errordialog.h" #include "dialogs/extractingprogressdialog.h" #include "utils/encoderassistant.h" class MainWindow : public KXmlGuiWindow { Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(QWidget *parent = nullptr); ~MainWindow() override; private: bool firstStart(); private Q_SLOTS: void eject(); void cddb_lookup(); void cddb_submit(); void rip(); void configure(); void new_audio_disc_detected(); void audio_disc_removed(); void cddb_lookup_start(); void cddb_lookup_done(const bool successful); void update_layout(); void enable_layout(bool enabled); void enable_submit(bool enabled = true); void disable_submit(); void configuration_updated(const QString &dialog_name); void current_profile_updated_from_ui(int row); void update_profile_action(int index); void update_profile_action(); void split_titles(); void swap_artists_and_titles(); void capitalize(); void auto_fill_artists(); void toggle(const QModelIndex &idx); void resizeColumns(); void select_all(); void select_none(); void invert_selection(); void cdda_context_menu(const QPoint &pos); void selection_changed(const int num_selected); private: CDDAModel *cdda_model; ProfileModel *profile_model; QLabel *profile_label; KComboBox *profile_combobox; void setup_actions(); void setup_layout(); QTreeView *cdda_tree_view; QDockWidget *cdda_header_dock; CDDAHeaderWidget *cdda_header_widget; bool layout_enabled; int current_profile_index; void set_profile(int profile_index); }; #endif diff --git a/models/cddamodel.cpp b/models/cddamodel.cpp index 8b690b2..5a37802 100644 --- a/models/cddamodel.cpp +++ b/models/cddamodel.cpp @@ -1,1039 +1,1039 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "cddamodel.h" CDDAModel::CDDAModel(QObject *parent) : QAbstractTableModel(parent) { - pn = 0; + pn = nullptr; _device.clear(); _udi.clear(); devices = new CDDADevices(this); if (!devices) { qDebug() << "Unable to create devices object. low mem?"; error = Error(i18n("Unable to create devices object."), i18n("This is an internal error. Check your hardware. If all okay please make bug report."), Error::ERROR, this); return; } connect(devices, SIGNAL(audioDiscDetected(const QString &)), this, SLOT(new_audio_disc_available(const QString &))); connect(devices, SIGNAL(audioDiscRemoved(const QString &)), this, SLOT(audio_disc_removed(const QString &))); cddb = new KCDDB::Client(); if (!cddb) { qDebug() << "Unable to create KCDDB object. Low mem?"; error = Error(i18n("Unable to create KCDDB object."), i18n("This is an internal error. Check your hardware. If all okay please make bug report."), Error::ERROR, this); return; } connect(cddb, SIGNAL(finished(KCDDB::Result)), this, SLOT(lookup_cddb_done(KCDDB::Result))); cddb_transaction_pending = false; _cover = new CachedImage(); cd_info.clear(); modified = false; _empty = true; QTimer::singleShot(200, devices, SLOT(scanBus())); } CDDAModel::~CDDAModel() { delete _cover; delete cddb; delete devices; if (pn) delete pn; } int CDDAModel::rowCount(const QModelIndex &parent) const { if (!pn) return 0; return parent.isValid() ? 0 : pn->numOfTracks(); } int CDDAModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return CDDA_MODEL_COLUMN_COUNT; } QVariant CDDAModel::data(const QModelIndex &index, int role) const { if (!pn) { return QVariant(); } if (!index.isValid()) { return QVariant(); } if ((index.row() < 0) || (index.row() >= numOfTracks())) { return QVariant(); } if (role == Qt::TextAlignmentRole) { return int(Qt::AlignLeft | Qt::AlignVCenter); } /*if (role == Qt::ForegroundRole) { switch (index.column()) { case CDDA_MODEL_COLUMN_ARTIST_INDEX : if (!isTrackArtistValid(index.row()+1)) return qVariantFromValue(QColor(Qt::gray)); break; case CDDA_MODEL_COLUMN_TITLE_INDEX : if (!isTrackTitleValid(index.row()+1)) return qVariantFromValue(QColor(Qt::gray)); break; } }*/ if ((role == Qt::DisplayRole) || (role == Qt::CheckStateRole && index.column() == CDDA_MODEL_COLUMN_RIP_INDEX) || (role == CDDA_MODEL_INTERNAL_ROLE) || (role == Qt::EditRole)) { switch (index.column()) { case CDDA_MODEL_COLUMN_RIP_INDEX: if (role == Qt::CheckStateRole) { return isTrackInSelection(index.row() + 1) ? Qt::Checked : Qt::Unchecked; } break; case CDDA_MODEL_COLUMN_TRACK_INDEX: return index.row() + 1 + (trackOffset() > 1 ? trackOffset() : 0); case CDDA_MODEL_COLUMN_LENGTH_INDEX: if (role == CDDA_MODEL_INTERNAL_ROLE) return lengthOfTrack(index.row() + 1); else return QString("%1:%2").arg(lengthOfTrack(index.row() + 1) / 60, 2, 10, QChar('0')).arg(lengthOfTrack(index.row() + 1) % 60, 2, 10, QChar('0')); case CDDA_MODEL_COLUMN_ARTIST_INDEX: if (isAudioTrack(index.row() + 1)) { QString a = cd_info.track(index.row()).get(KCDDB::Artist).toString(); return a; } break; case CDDA_MODEL_COLUMN_TITLE_INDEX: if (isAudioTrack(index.row() + 1)) { QString t = cd_info.track(index.row()).get(KCDDB::Title).toString(); if (t.isEmpty()) return i18n("Track %1", index.row() + 1); return t; } break; default:; } } return QVariant(); } bool CDDAModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!pn) { return false; } if (!index.isValid()) { return false; } if ((index.row() < 0) || (index.row() >= numOfTracks())) { return false; } if (role == Qt::EditRole) { bool changed = false; switch (index.column()) { case CDDA_MODEL_COLUMN_ARTIST_INDEX: if (value != cd_info.track(index.row()).get(KCDDB::Artist)) { cd_info.track(index.row()).set(KCDDB::Artist, value); changed = true; } break; case CDDA_MODEL_COLUMN_TITLE_INDEX: if (value != cd_info.track(index.row()).get(KCDDB::Title)) { cd_info.track(index.row()).set(KCDDB::Title, value); changed = true; } break; default: return false; } if (changed) { emit dataChanged(index, index); modify(); } return changed; } return false; } QVariant CDDAModel::headerData(int section, Qt::Orientation orientation, int role) const { Q_UNUSED(orientation); if (orientation == Qt::Horizontal) { switch (role) { case Qt::DisplayRole: switch (section) { case CDDA_MODEL_COLUMN_RIP_INDEX: return CDDA_MODEL_COLUMN_RIP_LABEL; case CDDA_MODEL_COLUMN_TRACK_INDEX: return CDDA_MODEL_COLUMN_TRACK_LABEL; case CDDA_MODEL_COLUMN_LENGTH_INDEX: return CDDA_MODEL_COLUMN_LENGTH_LABEL; case CDDA_MODEL_COLUMN_ARTIST_INDEX: return CDDA_MODEL_COLUMN_ARTIST_LABEL; case CDDA_MODEL_COLUMN_TITLE_INDEX: return CDDA_MODEL_COLUMN_TITLE_LABEL; default:; } break; case Qt::TextAlignmentRole: return Qt::AlignLeft; default:; } } else if (orientation == Qt::Vertical) { if (role == Qt::DisplayRole) { return QVariant(section + 1); } } return QVariant(); } Qt::ItemFlags CDDAModel::flags(const QModelIndex &index) const { Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; if ((index.column() == CDDA_MODEL_COLUMN_ARTIST_INDEX) || (index.column() == CDDA_MODEL_COLUMN_TITLE_INDEX)) { flags |= Qt::ItemIsEditable; } if (!isAudioTrack(index.row() + 1)) return Qt::ItemIsEnabled; return flags; } void CDDAModel::setArtist(const QString &a) { if (!pn) return; if (a != cd_info.get(KCDDB::Artist).toString()) { cd_info.set(KCDDB::Artist, a); modify(); reset(); } } const QString CDDAModel::artist() const { if (!pn) return QString(); QString a = cd_info.get(KCDDB::Artist).toString(); return a; } void CDDAModel::setTitle(const QString &t) { if (!pn) return; if (t != cd_info.get(KCDDB::Title).toString()) { cd_info.set(KCDDB::Title, t); modify(); reset(); } } const QString CDDAModel::title() const { if (!pn) return QString(); QString t = cd_info.get(KCDDB::Title).toString(); return t; } void CDDAModel::setCategory(const QString &c) { if (!pn) return; QStringList validCategories; validCategories << "blues" << "classical" << "country" << "data" << "folk" << "jazz" << "misc" << "newage" << "reggae" << "rock" << "soundtrack"; if (!validCategories.contains(c)) return; if (c != cd_info.get(KCDDB::Category).toString()) { cd_info.set(KCDDB::Category, c); modify(); reset(); } } const QString CDDAModel::category() const { if (!pn) return QString(); return cd_info.get(KCDDB::Category).toString(); } void CDDAModel::setGenre(const QString &g) { if (!pn) return; if (g != cd_info.get(KCDDB::Genre).toString()) { cd_info.set(KCDDB::Genre, g); modify(); reset(); } } const QString CDDAModel::genre() const { if (!pn) return QString(); return cd_info.get(KCDDB::Genre).toString(); } void CDDAModel::setYear(const QString &year) { if (!pn) return; if (year != cd_info.get(KCDDB::Year).toString()) { cd_info.set(KCDDB::Year, year); modify(); reset(); } } const QString CDDAModel::year() const { if (!pn) return QString(); return cd_info.get(KCDDB::Year).toString(); } void CDDAModel::setExtendedData(const QStringList &e) { if (!pn) return; if (e != cd_info.get(KCDDB::Comment).toStringList()) { cd_info.set(KCDDB::Comment, e); modify(); reset(); } } const QStringList CDDAModel::extendedData() const { if (!pn) return QStringList(); return cd_info.get(KCDDB::Comment).toStringList(); } void CDDAModel::setCDNum(const int n) { if (!pn) return; if (n != cd_info.get("DNO").toInt()) { cd_info.set("DNO", n); modify(); reset(); } } int CDDAModel::cdNum() const { if (!pn) return -1; if (!isMultiCD()) return 0; return cd_info.get("DNO").toInt(); } void CDDAModel::setTrackOffset(const int n) { if (!pn) return; if (n != cd_info.get("DTRACKOFFSET").toInt()) { cd_info.set("DTRACKOFFSET", n); modify(); reset(); } } int CDDAModel::trackOffset() const { if (!pn) return -1; return cd_info.get("DTRACKOFFSET").toInt(); } int CDDAModel::guessMultiCD(QString &newTitle) const { if (!pn) return -1; QString t = cd_info.get(KCDDB::Title).toString(); QRegExp rx1("[\\(|\\[]* *([c|C][d|D]|[d|D][i|I][s|S][k|c|K|C]) *[0-9]* *[\\)|\\]]* *$"); int i = rx1.indexIn(t); if (i >= 0) { QString frac = t.mid(i); QRegExp rx2("(\\d+)"); rx2.indexIn(frac); bool ok; int cdnum = rx2.cap(0).toInt(&ok); if (ok) { if (cdnum < 0) return -1; if (cdnum == 0) cdnum = 1; newTitle = t.left(i).trimmed(); return cdnum; } } return -1; } void CDDAModel::setMultiCD(const bool multi) { if (!pn) return; if (multi != cd_info.get("DMULTICD").toBool()) { cd_info.set("DMULTICD", multi); modify(); reset(); } } bool CDDAModel::isMultiCD() const { if (!pn) return false; return cd_info.get("DMULTICD").toBool(); } void CDDAModel::setCustomData(const QString &type, const QVariant &data) { if (!pn) return; if (data != cd_info.get(type)) { cd_info.set(type, data); modify(); reset(); } } const QVariant CDDAModel::customData(const QString &type) const { if (!pn) return QVariant(); return cd_info.get(type); } void CDDAModel::setCustomDataPerTrack(const int n, const QString &type, const QVariant &data) { if (!pn) return; if (data != cd_info.track(n).get(type)) { cd_info.track(n).set(type, data); modify(); reset(); } } const QVariant CDDAModel::getCustomDataPerTrack(const int n, const QString &type) { if (!pn) return QVariant(); return cd_info.track(n).get(type); } CachedImage *CDDAModel::cover() const { return _cover; } const QImage CDDAModel::coverImage() const { return _cover->coverImage(); } quint16 CDDAModel::coverChecksum() const { return _cover->checksum(); } bool CDDAModel::setCover(const QByteArray &data) { if (_cover->load(data)) { reset(); return true; } else { error = _cover->lastError(); } return false; } bool CDDAModel::setCover(const QString &filename) { if (_cover->load(filename)) { reset(); return true; } else { error = _cover->lastError(); } return false; } bool CDDAModel::saveCoverToFile(const QString &filename) { if (_cover->save(filename)) { return true; } else { error = _cover->lastError(); } return false; } bool CDDAModel::isCoverEmpty() const { return _cover->isEmpty(); } void CDDAModel::clearCover() { if (_cover->isEmpty()) return; _cover->clear(); reset(); } const QString CDDAModel::coverSupportedMimeTypeList() const { return _cover->supportedMimeTypeList(); } bool CDDAModel::guessVarious() const { if (!pn) return false; QString a; for (int i = 0; i < cd_info.numberOfTracks(); ++i) { if ((i > 0) && (cd_info.track(i).get(KCDDB::Artist).toString().toLower() != a.toLower())) return true; a = cd_info.track(i).get(KCDDB::Artist).toString(); } return false; } void CDDAModel::setVarious(bool various) { if (!pn) return; if (various != cd_info.get("DVARIOUS").toBool()) { cd_info.set("DVARIOUS", various); modify(); } } bool CDDAModel::isVarious() { if (!pn) return false; return cd_info.get("DVARIOUS").toBool(); } void CDDAModel::swapArtistAndTitleOfTracks() { if (!pn) return; for (int i = 0; i < cd_info.numberOfTracks(); ++i) { QVariant tmp = cd_info.track(i).get(KCDDB::Artist); cd_info.track(i).set(KCDDB::Artist, cd_info.track(i).get(KCDDB::Title)); cd_info.track(i).set(KCDDB::Title, tmp); } modified = true; emit cddbDataModified(); reset(); } void CDDAModel::swapArtistAndTitle() { if (!pn) return; QVariant tmp = cd_info.get(KCDDB::Title); cd_info.set(KCDDB::Title, cd_info.get(KCDDB::Artist)); cd_info.set(KCDDB::Artist, tmp); modified = true; emit cddbDataModified(); reset(); } void CDDAModel::splitTitleOfTracks(const QString ÷r) { if (!pn) return; for (int i = 0; i < cd_info.numberOfTracks(); ++i) { int splitPos = cd_info.track(i).get(KCDDB::Title).toString().indexOf(divider); if (splitPos >= 0) { // split QString title = cd_info.track(i).get(KCDDB::Title).toString().mid(splitPos + divider.length()); QString artist = cd_info.track(i).get(KCDDB::Title).toString().left(splitPos); cd_info.track(i).set(KCDDB::Artist, artist); cd_info.track(i).set(KCDDB::Title, title); } } modified = true; emit cddbDataModified(); reset(); } void CDDAModel::capitalizeTracks() { if (!pn) return; for (int i = 0; i < cd_info.numberOfTracks(); ++i) { cd_info.track(i).set(KCDDB::Artist, capitalize(cd_info.track(i).get(KCDDB::Artist).toString())); cd_info.track(i).set(KCDDB::Title, capitalize(cd_info.track(i).get(KCDDB::Title).toString())); } modified = true; emit cddbDataModified(); reset(); } void CDDAModel::capitalizeHeader() { if (!pn) return; cd_info.set(KCDDB::Artist, capitalize(cd_info.get(KCDDB::Artist).toString())); cd_info.set(KCDDB::Title, capitalize(cd_info.get(KCDDB::Title).toString())); modified = true; emit cddbDataModified(); reset(); } void CDDAModel::setTitleArtistsFromHeader() { if (!pn) return; for (int i = 0; i < cd_info.numberOfTracks(); ++i) { cd_info.track(i).set(KCDDB::Artist, cd_info.get(KCDDB::Artist)); } modified = true; emit cddbDataModified(); reset(); } int CDDAModel::numOfTracks() const { if (!pn) return 0; return pn->numOfTracks(); } int CDDAModel::numOfAudioTracks() const { int c = 0; for (int i = 1; i <= numOfTracks(); ++i) { if (isAudioTrack(i)) ++c; } return c; } int CDDAModel::numOfAudioTracksInSelection() const { return sel_tracks.count(); } int CDDAModel::length() const { if (!pn) return 0; return pn->length(); } int CDDAModel::lengthOfAudioTracks() const { int c = 0; for (int i = 1; i <= numOfTracks(); ++i) { if (isAudioTrack(i)) c += lengthOfTrack(i); } return c; } int CDDAModel::lengthOfAudioTracksInSelection() const { QSet::ConstIterator it(sel_tracks.begin()), end(sel_tracks.end()); int l = 0; for (; it != end; ++it) { if (isAudioTrack(*it)) l += lengthOfTrack(*it); } return l; } int CDDAModel::lengthOfTrack(int n) const { if (!pn) return 0; return pn->lengthOfTrack(n); } const QList CDDAModel::discSignature() const { if (!pn) return QList(); return pn->discSignature(); } bool CDDAModel::isAudioTrack(int n) const { if (!pn) return false; return pn->isAudioTrack(n); } void CDDAModel::clear() { cd_info.clear(); clearCover(); reset(); } void CDDAModel::toggle(int row) { _toggle(row + 1); emit hasSelection(0 != sel_tracks.count()); emit selectionChanged(sel_tracks.count()); } bool CDDAModel::isTrackInSelection(int n) const { return sel_tracks.contains(n); } void CDDAModel::invertSelection() { for (int i = 1; i <= numOfTracks(); ++i) { if (isAudioTrack(i)) _toggle(i); } emit hasSelection(0 != sel_tracks.count()); emit selectionChanged(sel_tracks.count()); } void CDDAModel::selectAll() { sel_tracks.clear(); invertSelection(); } void CDDAModel::selectNone() { sel_tracks.clear(); emit hasSelection(false); emit selectionChanged(0); } bool CDDAModel::isModified() const { return modified; } void CDDAModel::confirm() { modified = false; } Error CDDAModel::lastError() const { return error; } void CDDAModel::lookupCDDB() { if (!pn) return; qDebug() << "lookupCDDB called"; if (cddb_transaction_pending) { qDebug() << "CDDB transaction already in progress."; return; } cddb_transaction_pending = true; emit cddbLookupStarted(); cddb->config().reparse(); cddb->setBlockingMode(false); cddb->lookup(pn->discSignature()); } bool CDDAModel::submitCDDB() { if (!pn) return true; qDebug() << "submitCDDB called"; if (cddb_transaction_pending) { qDebug() << "CDDB transaction already in progress."; error = Error(i18n("CDDB transaction already in progress."), i18n("A CDDB transaction is already in progress. Please wait until it has finished and try again."), Error::ERROR, this); return false; } cddb_transaction_pending = true; cddb->config().reparse(); cddb->setBlockingMode(true); if (category().isEmpty()) { setCategory("rock"); } KCDDB::Result result = cddb->submit(cd_info, pn->discSignature()); if (result != KCDDB::Success) { switch (result) { case KCDDB::ServerError: error = Error(KCDDB::resultToString(result), i18n("There is an error with the CDDB server. Please wait or contact the administrator of the CDDB server."), Error::ERROR, this); break; case KCDDB::HostNotFound: error = Error(KCDDB::resultToString(result), i18n("Cannot find the CDDB server. Check your network. Maybe the CDDB server is offline."), Error::ERROR, this); break; case KCDDB::NoResponse: error = Error(KCDDB::resultToString(result), i18n("Please wait, maybe the server is busy, or contact the CDDB server administrator."), Error::ERROR, this); break; case KCDDB::CannotSave: error = Error(KCDDB::resultToString(result), i18n("Please contact the CDDB server administrator."), Error::ERROR, this); break; case KCDDB::InvalidCategory: error = Error(KCDDB::resultToString(result), i18n("This should not happen. Please make a bug report."), Error::ERROR, this); break; case KCDDB::UnknownError:; case KCDDB::NoRecordFound:; case KCDDB::MultipleRecordFound:; case KCDDB::Success:; default: error = Error(KCDDB::resultToString(result), i18n("Please make a bug report and contact the CDDB server administrator."), Error::ERROR, this); break; } return false; } error = Error(); confirm(); cddb_transaction_pending = false; emit cddbDataSubmited(true); return true; } void CDDAModel::eject() { devices->eject(_udi); } void CDDAModel::new_audio_disc_available(const QString &udi) { if (pn) return; _device = devices->blockDevice(udi); _udi = udi; pn = new CDDAParanoia(this); if (!pn) { qDebug() << "Unable to create paranoia class. low mem?"; error = Error(i18n("Unable to create CDDA paranoia object."), i18n("This is an internal error. Check your hardware. If all okay please make bug report."), Error::ERROR, this); return; } pn->setDevice(_device); qDebug() << "new audio disc detected (" << udi << ", " << _device << ")"; clear(); confirm(); sel_tracks.clear(); for (int i = 1; i <= pn->numOfTracks(); ++i) { if (isAudioTrack(i)) sel_tracks.insert(i); } emit hasSelection(0 != sel_tracks.size()); emit audioDiscDetected(); } void CDDAModel::audio_disc_removed(const QString &udi) { qDebug() << "audio disc removed (" << udi << ")"; _device.clear(); _udi.clear(); if (pn) delete pn; - pn = NULL; + pn = nullptr; emit audioDiscRemoved(); } void CDDAModel::disc_information_modified() { qDebug() << "disc info changed"; set_default_values(); setVarious(guessVarious()); reset(); } void CDDAModel::lookup_cddb_done(KCDDB::Result result) { if ((result != KCDDB::Success) && (result != KCDDB::MultipleRecordFound)) { switch (result) { case KCDDB::ServerError: error = Error(KCDDB::resultToString(result), i18n("There is an error with the CDDB server. Please wait or contact the administrator of the CDDB server."), Error::ERROR, this); break; case KCDDB::HostNotFound: error = Error(KCDDB::resultToString(result), i18n("Cannot find the CDDB server. Check your network. Maybe the CDDB server is offline."), Error::ERROR, this); break; case KCDDB::NoResponse: error = Error(KCDDB::resultToString(result), i18n("Please wait, maybe the server is busy, or contact the CDDB server administrator."), Error::ERROR, this); break; case KCDDB::InvalidCategory: error = Error(KCDDB::resultToString(result), i18n("This should not happen. Please make a bug report."), Error::ERROR, this); break; case KCDDB::UnknownError: error = Error(KCDDB::resultToString(result), i18n("Please make a bug report and contact the CDDB server administrator."), Error::ERROR, this); break; case KCDDB::NoRecordFound:; case KCDDB::MultipleRecordFound:; case KCDDB::Success:; default: error = Error(KCDDB::resultToString(result), i18n("This means no data found in the CDDB database."), Error::ERROR, this); } emit cddbLookupDone(false); return; } KCDDB::CDInfo info = cddb->lookupResponse().constFirst(); if (cddb->lookupResponse().count() > 1) { KCDDB::CDInfoList cddb_info = cddb->lookupResponse(); KCDDB::CDInfoList::iterator it; QStringList list; for (it = cddb_info.begin(); it != cddb_info.end(); ++it) { list.append(QString("%1, %2, %3, %4").arg((it->get(KCDDB::Artist).toString()), it->get(KCDDB::Title).toString(), it->get(KCDDB::Genre).toString(), it->get(KCDDB::Year).toString())); } bool ok = false; // Uses a ComboBox, could use UseListViewForComboBoxItems if necessary - QString res = QInputDialog::getItem(nullptr, i18n("Select CDDB Entry"), i18n("Select a CDDB entry:"), list, 0, false, &ok, NULL); + QString res = QInputDialog::getItem(nullptr, i18n("Select CDDB Entry"), i18n("Select a CDDB entry:"), list, 0, false, &ok, nullptr); if (ok) { // The user selected an item and pressed OK int c = 0; for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) { if (*it == res) break; c++; } if (c < cddb_info.size()) info = cddb_info[c]; } else { emit cddbLookupDone(true); return; // user pressed cancel } } cd_info = info; set_default_values(); setVarious(guessVarious()); if (isVarious() && QLatin1String("Various") == artist()) { setArtist(i18n("Various Artists")); } QString newTitle; int cdnum = guessMultiCD(newTitle); if (cdnum > 0) { setMultiCD(true); setCDNum(cdnum); setTitle(newTitle); } reset(); cddb_transaction_pending = false; _empty = false; emit cddbLookupDone(true); } void CDDAModel::_toggle(const unsigned int track) { if (sel_tracks.contains(track)) { sel_tracks.remove(track); } else { sel_tracks.insert(track); } } const QString CDDAModel::capitalize(const QString &s) { QStringList stringlist = s.split(' ', QString::SkipEmptyParts); for (int i = 0; i < stringlist.count(); i++) { QString string = stringlist[i].toLower(); int j = 0; while (((string[j] == '(') || (string[j] == '[') || (string[j] == '{')) && (j < string.length())) j++; string[j] = string[j].toUpper(); stringlist[i] = string; } return stringlist.join(" "); } void CDDAModel::set_default_values() { if (cd_info.get(KCDDB::Year).toString().isEmpty()) cd_info.set(KCDDB::Year, QString("%1").arg(QDate::currentDate().year())); cd_info.set("DNO", 1); cd_info.set("DTRACKOFFSET", 1); cd_info.set("DMULTICD", false); } void CDDAModel::modify() { modified = true; _empty = false; emit cddbDataModified(); } diff --git a/models/cddamodel.h b/models/cddamodel.h index 0436125..b9da475 100644 --- a/models/cddamodel.h +++ b/models/cddamodel.h @@ -1,230 +1,230 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CDDAMODEL_H #define CDDAMODEL_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "utils/cachedimage.h" #include "utils/cddadevices.h" #include "utils/cddaparanoia.h" #include "utils/error.h" #define CDDA_MODEL_COLUMN_RIP_LABEL i18n("Rip") #define CDDA_MODEL_COLUMN_TRACK_LABEL i18n("Track") #define CDDA_MODEL_COLUMN_ARTIST_LABEL i18n("Artist") #define CDDA_MODEL_COLUMN_TITLE_LABEL i18n("Title") #define CDDA_MODEL_COLUMN_LENGTH_LABEL i18n("Length") enum CDDAColumms { CDDA_MODEL_COLUMN_RIP_INDEX = 0, CDDA_MODEL_COLUMN_TRACK_INDEX, CDDA_MODEL_COLUMN_ARTIST_INDEX, CDDA_MODEL_COLUMN_TITLE_INDEX, CDDA_MODEL_COLUMN_LENGTH_INDEX, CDDA_MODEL_COLUMN_COUNT }; #define CDDA_MODEL_INTERNAL_ROLE 1982 /** kde audio disc model **/ class CDDAModel : public QAbstractTableModel { Q_OBJECT public: - explicit CDDAModel(QObject *parent = 0); + explicit CDDAModel(QObject *parent = nullptr); ~CDDAModel() override; inline CDDAParanoia *paranoia() const { return pn; } inline const QString &device() const { return _device; } int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; void setArtist(const QString &a); const QString artist() const; void setTitle(const QString &t); const QString title() const; // category must be cddb compatible //(blues, classical, country, data, // folk, jazz, misc, newage, reggae, // rock, soundtrack) void setCategory(const QString &c); const QString category() const; void setGenre(const QString &g); const QString genre() const; void setYear(const QString &year); const QString year() const; void setExtendedData(const QStringList &e); const QStringList extendedData() const; void setCDNum(const int n); int cdNum() const; void setTrackOffset(const int n); int trackOffset() const; int guessMultiCD(QString &newTitle) const; void setMultiCD(const bool multi); bool isMultiCD() const; void setCustomData(const QString &type, const QVariant &data); const QVariant customData(const QString &type) const; void setCustomDataPerTrack(const int n, const QString &type, const QVariant &data); const QVariant getCustomDataPerTrack(const int n, const QString &type); CachedImage *cover() const; const QImage coverImage() const; quint16 coverChecksum() const; bool setCover(const QByteArray &data); bool setCover(const QString &filename); bool saveCoverToFile(const QString &filename); bool isCoverEmpty() const; void clearCover(); const QString coverSupportedMimeTypeList() const; bool guessVarious() const; void setVarious(bool various); bool isVarious(); void swapArtistAndTitleOfTracks(); void swapArtistAndTitle(); void splitTitleOfTracks(const QString ÷r); void capitalizeTracks(); void capitalizeHeader(); void setTitleArtistsFromHeader(); int numOfTracks() const; int numOfAudioTracks() const; int numOfAudioTracksInSelection() const; int length() const; int lengthOfAudioTracks() const; int lengthOfAudioTracksInSelection() const; int lengthOfTrack(int n) const; const QList discSignature() const; bool isAudioTrack(int n) const; void clear(); inline bool empty() { return _empty; } inline const QSet &selectedTracks() const { return sel_tracks; } void toggle(int row); bool isTrackInSelection(int n) const; void invertSelection(); void selectAll(); void selectNone(); bool isModified() const; void confirm(); Error lastError() const; public slots: void lookupCDDB(); bool submitCDDB(); void eject(); signals: void audioDiscDetected(); void audioDiscRemoved(); void cddbLookupStarted(); void cddbLookupDone(const bool successful); void cddbDataModified(); void cddbDataSubmited(const bool successful); void hasSelection(bool has_selection); void selectionChanged(const int num_selected); private slots: void new_audio_disc_available(const QString &udi); void audio_disc_removed(const QString &udi); void disc_information_modified(); void lookup_cddb_done(KCDDB::Result result); private: QString _device; QString _udi; CDDAParanoia *pn; CDDADevices *devices; KCDDB::Client *cddb; KCDDB::CDInfo cd_info; CachedImage *_cover; bool modified; bool _empty; // no metadata available yet Error error; bool cddb_transaction_pending; QSet sel_tracks; void _toggle(const unsigned int track); const QString capitalize(const QString &s); void set_default_values(); void modify(); }; #endif diff --git a/models/profilemodel.h b/models/profilemodel.h index 08db7b5..49e0365 100644 --- a/models/profilemodel.h +++ b/models/profilemodel.h @@ -1,246 +1,246 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROFILEMODEL_HEADER #define PROFILEMODEL_HEADER #include #include #include #include #include #include #include #include "utils/encoderassistant.h" #include "utils/error.h" #define DEFAULT_PROFILEINDEX -1 #define DEFAULT_NAME "" #define DEFAULT_ICON "audio-x-generic" #define DEFAULT_ENCODER_SELECTED 0 #define DEFAULT_ENCODER_PARAMETERS "" #define DEFAULT_PATTERN "$" VAR_ALBUM_ARTIST "/$" VAR_ALBUM_TITLE "/$" VAR_TRACK_NO " - $" VAR_TRACK_TITLE ".$" VAR_SUFFIX #define DEFAULT_FAT32 false #define DEFAULT_UNDERSCORE false #define DEFAULT_2DIGITSTRACKNUM true #define DEFAULT_SC true #define DEFAULT_SC_SCALE false #define DEFAULT_SC_SIZE QSize(600, 600) #define DEFAULT_SC_FORMAT "JPEG" #define DEFAULT_SC_NAME "$" VAR_ALBUM_TITLE ".$" VAR_SUFFIX #define DEFAULT_PL true #define DEFAULT_PL_FORMAT "M3U" #define DEFAULT_PL_NAME "$" VAR_ALBUM_TITLE ".$" VAR_SUFFIX #define DEFAULT_PL_ABS_FILE_PATH false #define DEFAULT_PL_UTF8 true #define DEFAULT_INF false #define DEFAULT_INF_TEXT QStringList() #define DEFAULT_INF_NAME "info" #define DEFAULT_INF_SUFFIX "nfo" #define DEFAULT_HL false #define DEFAULT_HL_FORMAT "SFV" #define DEFAULT_HL_NAME "checksums.$" VAR_SUFFIX #define DEFAULT_CUE false #define DEFAULT_CUE_NAME "$" VAR_ALBUM_ARTIST " - $" VAR_ALBUM_TITLE ".$" VAR_SUFFIX #define DEFAULT_SF false #define DEFAULT_SF_NAME "$" VAR_ALBUM_ARTIST "/$" VAR_ALBUM_TITLE "/$" VAR_ALBUM_ARTIST " - $" VAR_ALBUM_TITLE ".$" VAR_SUFFIX enum ProfileColumns { PROFILE_MODEL_COLUMN_PROFILEINDEX_INDEX = 0, PROFILE_MODEL_COLUMN_NAME_INDEX, PROFILE_MODEL_COLUMN_ICON_INDEX, PROFILE_MODEL_COLUMN_ENCODER_SELECTED_INDEX, PROFILE_MODEL_COLUMN_PATTERN_INDEX, PROFILE_MODEL_COLUMN_FAT32COMPATIBLE_INDEX, PROFILE_MODEL_COLUMN_UNDERSCORE_INDEX, PROFILE_MODEL_COLUMN_2DIGITSTRACKNUM_INDEX, PROFILE_MODEL_COLUMN_SC_INDEX, PROFILE_MODEL_COLUMN_SC_SCALE_INDEX, PROFILE_MODEL_COLUMN_SC_SIZE_INDEX, PROFILE_MODEL_COLUMN_SC_FORMAT_INDEX, PROFILE_MODEL_COLUMN_SC_NAME_INDEX, PROFILE_MODEL_COLUMN_PL_INDEX, PROFILE_MODEL_COLUMN_PL_FORMAT_INDEX, PROFILE_MODEL_COLUMN_PL_NAME_INDEX, PROFILE_MODEL_COLUMN_PL_ABS_FILE_PATH_INDEX, PROFILE_MODEL_COLUMN_PL_UTF8_INDEX, PROFILE_MODEL_COLUMN_INF_INDEX, PROFILE_MODEL_COLUMN_INF_TEXT_INDEX, PROFILE_MODEL_COLUMN_INF_NAME_INDEX, PROFILE_MODEL_COLUMN_INF_SUFFIX_INDEX, PROFILE_MODEL_COLUMN_HL_INDEX, PROFILE_MODEL_COLUMN_HL_FORMAT_INDEX, PROFILE_MODEL_COLUMN_HL_NAME_INDEX, PROFILE_MODEL_COLUMN_CUE_INDEX, PROFILE_MODEL_COLUMN_CUE_NAME_INDEX, PROFILE_MODEL_COLUMN_SF_INDEX, PROFILE_MODEL_COLUMN_SF_NAME_INDEX, PROFILE_MODEL_COLUMN_ENCODER_LAME_PARAMETERS_INDEX, PROFILE_MODEL_COLUMN_ENCODER_OGGENC_PARAMETERS_INDEX, PROFILE_MODEL_COLUMN_ENCODER_FLAC_PARAMETERS_INDEX, PROFILE_MODEL_COLUMN_ENCODER_FAAC_PARAMETERS_INDEX, PROFILE_MODEL_COLUMN_ENCODER_WAVE_PARAMETERS_INDEX, PROFILE_MODEL_COLUMN_ENCODER_CUSTOM_PARAMETERS_INDEX, PROFILE_MODEL_COLUMN_NUM }; #define PROFILE_MODEL_PROFILEINDEX_KEY "profile_key" #define PROFILE_MODEL_NAME_KEY "name" #define PROFILE_MODEL_ICON_KEY "icon" #define PROFILE_MODEL_ENCODER_SELECTED_KEY "current_encoder" #define PROFILE_MODEL_PATTERN_KEY "pattern" #define PROFILE_MODEL_FAT32COMPATIBLE_KEY "fat32_compatible" #define PROFILE_MODEL_UNDERSCORE_KEY "underscore" #define PROFILE_MODEL_2DIGITSTRACKNUM_KEY "2_digits_tracknum" #define PROFILE_MODEL_SC_KEY "sc" #define PROFILE_MODEL_SC_SCALE_KEY "sc_scale" #define PROFILE_MODEL_SC_SIZE_KEY "sc_size" #define PROFILE_MODEL_SC_FORMAT_KEY "sc_format" #define PROFILE_MODEL_SC_NAME_KEY "sc_name" #define PROFILE_MODEL_PL_KEY "pl" #define PROFILE_MODEL_PL_FORMAT_KEY "pl_format" #define PROFILE_MODEL_PL_NAME_KEY "pl_name" #define PROFILE_MODEL_PL_ABS_FILE_PATH_KEY "pl_abs_file_path" #define PROFILE_MODEL_PL_UTF8_KEY "pl_utf8" #define PROFILE_MODEL_INF_KEY "inf" #define PROFILE_MODEL_INF_TEXT_KEY "inf_text" #define PROFILE_MODEL_INF_NAME_KEY "inf_name" #define PROFILE_MODEL_INF_SUFFIX_KEY "inf_suffix" #define PROFILE_MODEL_HL_KEY "hl" #define PROFILE_MODEL_HL_FORMAT_KEY "hl_format" #define PROFILE_MODEL_HL_NAME_KEY "hl_name" #define PROFILE_MODEL_CUE_KEY "cue" #define PROFILE_MODEL_CUE_NAME_KEY "cue_name" #define PROFILE_MODEL_SF_KEY "sf" #define PROFILE_MODEL_SF_NAME_KEY "sf_name" #define PROFILE_MODEL_COLUMN_ENCODER_LAME_PARAMETERS_KEY "lame_parameters" #define PROFILE_MODEL_COLUMN_ENCODER_OGGENC_PARAMETERS_KEY "oggenc_parameters" #define PROFILE_MODEL_COLUMN_ENCODER_FLAC_PARAMETERS_KEY "flac_parameters" #define PROFILE_MODEL_COLUMN_ENCODER_FAAC_PARAMETERS_KEY "faac_parameters" #define PROFILE_MODEL_COLUMN_ENCODER_WAVE_PARAMETERS_KEY "wave_parameters" #define PROFILE_MODEL_COLUMN_ENCODER_CUSTOM_PARAMETERS_KEY "custom_parameters" #define LABEL_MOBILE_QUALITY i18n(" (Mobile Quality)") #define LABEL_NORMAL_QUALITY i18n(" (Normal Quality)") #define LABEL_EXTREME_QUALITY i18n(" (Extreme Quality)") typedef QMap Profile; /** audex profile model **/ class ProfileModel : public QAbstractTableModel { Q_OBJECT public: - explicit ProfileModel(QObject *parent = 0); + explicit ProfileModel(QObject *parent = nullptr); ~ProfileModel() override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; int currentProfileIndex() const; int currentProfileRow() const; int getRowByIndex(int profile_index) const; void clear(); bool nameExists(const QString &name) const; bool indexExists(int profile_index) const; int getNewIndex() const; void sortItems(); /**BEGIN: EncoderAssistant related */ void autoCreate(); // scans the system for encoders and create standard profiles EncoderAssistant::Encoder getSelectedEncoderFromCurrentIndex(); const Parameters getSelectedEncoderParametersFromCurrentIndex(); const QString getSelectedEncoderPatternFromCurrentIndex(); const QString getSelectedEncoderSuffixFromCurrentIndex(); const QString getSelectedEncoderNameAndVersion(); /**END: EncoderAssistant related */ Error lastError() const; public slots: void commit(); void revert() override; int copy(const int profileRow); bool saveProfilesToFile(const QString &filename); bool loadProfilesFromFile(const QString &filename); void setCurrentProfileIndex(int profile_index); int setRowAsCurrentProfileIndex(int row); // returns profile index signals: void profilesRemovedOrInserted(); void currentProfileIndexChanged(int index); private: const Profile p_new_profile(); QList p_cache; int p_current_profile_index; Error p_error; void p_new_name(QString &name); void p_save(KConfig *config); void p_load(KConfig *config); }; #endif diff --git a/utils/cddadevices.h b/utils/cddadevices.h index 1517d22..316a3bd 100644 --- a/utils/cddadevices.h +++ b/utils/cddadevices.h @@ -1,83 +1,83 @@ /* * AUDEX CDDA EXTRACTOR * * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef CDDADEVICES_H #define CDDADEVICES_H #include #include #include #include #include #include #include #include #include #include #include #include #include struct OpticalAudioDisc { QString name; Solid::Device device; }; class CDDADevices : public QObject { Q_OBJECT public: - explicit CDDADevices(QObject *parent = 0); + explicit CDDADevices(QObject *parent = nullptr); ~CDDADevices() override; const QString blockDevice(const QString &udi) const; const QStringList udiList() const; int discCount() const; public slots: void scanBus(); void eject(const QString &udi); // set display name void setName(const QString &udi, const QString &name); signals: void audioDiscDetected(const QString &udi); void audioDiscRemoved(const QString &udi); private slots: void p_solid_device_added(const QString &udi); void p_solid_device_removed(const QString &udi); private: QHash p_discs; bool p_is_optical_audio_disc(const Solid::Device &device) const; void p_clear(); }; #endif diff --git a/utils/cddaextractthread.cpp b/utils/cddaextractthread.cpp index e010ae6..216f386 100644 --- a/utils/cddaextractthread.cpp +++ b/utils/cddaextractthread.cpp @@ -1,268 +1,268 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "cddaextractthread.h" #include -static CDDAExtractThread *aet = 0; +static CDDAExtractThread *aet = nullptr; void paranoiaCallback(long sector, int status) { aet->createStatus(sector, status); } CDDAExtractThread::CDDAExtractThread(QObject *parent, CDDAParanoia *_paranoia) : QThread(parent) { paranoia = _paranoia; if (!paranoia) { qDebug() << "Paranoia object not found. low mem?"; emit error(i18n("Internal device error."), i18n("Check your device and make a bug report.")); return; } connect(paranoia, SIGNAL(error(const QString &, const QString &)), this, SLOT(slot_error(const QString &, const QString &))); overall_sectors_read = 0; paranoia_mode = 3; paranoia_retries = 20; never_skip = true; sample_offset = 0; sample_offset_done = false; track = 1; b_interrupt = false; b_error = false; read_error = false; scratch_detected = false; } CDDAExtractThread::~CDDAExtractThread() { } void CDDAExtractThread::start() { QThread::start(); } void CDDAExtractThread::run() { if (!paranoia) return; if (b_interrupt) return; b_interrupt = false; b_error = false; if ((sample_offset) && (!sample_offset_done)) { paranoia->sampleOffset(sample_offset); sample_offset_done = true; } if (track == 0) { first_sector = paranoia->firstSectorOfDisc(); last_sector = paranoia->lastSectorOfDisc(); } else { first_sector = paranoia->firstSectorOfTrack(track); last_sector = paranoia->lastSectorOfTrack(track); } if (first_sector < 0 || last_sector < 0) { emit info(i18n("Extracting finished.")); return; } qDebug() << "Sectors to read: " << QString("%1").arg(last_sector - first_sector); // status variable last_read_sector = 0; overlap = 0; read_sectors = 0; // track length sectors_all = last_sector - first_sector; sectors_read = 0; paranoia->setParanoiaMode(paranoia_mode); paranoia->setNeverSkip(never_skip); paranoia->setMaxRetries(paranoia_retries); paranoia->paranoiaSeek(first_sector, SEEK_SET); current_sector = first_sector; if (track > 0) { QString min = QString("%1").arg((sectors_all / 75) / 60, 2, 10, QChar('0')); QString sec = QString("%1").arg((sectors_all / 75) % 60, 2, 10, QChar('0')); emit info(i18n("Ripping track %1 (%2:%3)...", track, min, sec)); } else { emit info(i18n("Ripping whole CD as single track.")); } extract_protocol.append(i18n("Start reading track %1 with %2 sectors", track, sectors_all)); while (current_sector <= last_sector) { if (b_interrupt) { qDebug() << "Interrupt reading."; break; } // let the global paranoia callback have access to this // to emit signals aet = this; int16_t *buf = paranoia->paranoiaRead(paranoiaCallback); - if (0 == buf) { + if (nullptr == buf) { qDebug() << "Unrecoverable error in paranoia_read (sector " << current_sector << ")"; b_error = true; break; } else { current_sector++; QByteArray a((char *)buf, CD_FRAMESIZE_RAW); emit output(a); a.clear(); sectors_read++; overall_sectors_read++; float fraction = 0.0f; if (sectors_all > 0) fraction = (float)sectors_read / (float)sectors_all; emit progress((int)(100.0f * fraction), current_sector, overall_sectors_read); } } if (b_interrupt) emit error(i18n("User canceled extracting.")); if (b_error) emit error(i18n("An error occurred while ripping track %1.", track)); if ((!b_interrupt) && (!b_error)) { if (track > 0) { emit info(i18n("Ripping OK (Track %1).", track)); } else { emit info(i18n("Ripping OK.")); } } qDebug() << "Reading finished."; extract_protocol.append(i18n("Reading finished")); } void CDDAExtractThread::cancel() { b_interrupt = true; } bool CDDAExtractThread::isProcessing() { return !(b_interrupt || !isRunning()); } const QStringList &CDDAExtractThread::protocol() { return extract_protocol; } void CDDAExtractThread::slot_error(const QString &message, const QString &details) { emit error(message, details); } void CDDAExtractThread::createStatus(long sector, int status) { sector /= CD_FRAMESIZE_RAW / 2; QString tp_min = QString("%1").arg((current_sector / 75) / 60, 2, 10, QChar('0')); QString tp_sec = QString("%1").arg((current_sector / 75) % 60, 2, 10, QChar('0')); switch (status) { case -1: break; case -2: break; case PARANOIA_CB_READ: // no problem last_read_sector = sector; // this seems to be rather useless read_sectors++; read_error = false; scratch_detected = false; break; case PARANOIA_CB_VERIFY: // qDebug() << "Verifying jitter"; break; case PARANOIA_CB_FIXUP_EDGE: qDebug() << "Fixed edge jitter"; extract_protocol.append(i18n("Fixed edge jitter (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); break; case PARANOIA_CB_FIXUP_ATOM: qDebug() << "Fixed atom jitter"; extract_protocol.append(i18n("Fixed atom jitter (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); break; case PARANOIA_CB_SCRATCH: // scratch detected qDebug() << "Scratch detected"; if (!scratch_detected) { scratch_detected = true; emit warning(i18n("Scratch detected (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); } extract_protocol.append(i18n("SCRATCH DETECTED (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); break; case PARANOIA_CB_REPAIR: qDebug() << "Repair"; extract_protocol.append(i18n("Repair (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); break; case PARANOIA_CB_SKIP: // skipped sector qDebug() << "Skip"; emit warning(i18n("Skip sectors (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); extract_protocol.append(i18n("SKIP (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); break; case PARANOIA_CB_DRIFT: qDebug() << "Drift"; extract_protocol.append(i18n("Drift (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); break; case PARANOIA_CB_BACKOFF: qDebug() << "Backoff"; extract_protocol.append(i18n("Backoff (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); break; case PARANOIA_CB_OVERLAP: // sector does not seem to contain the current // sector but the amount of overlapped data // qDebug() << "overlap."; overlap = sector; break; case PARANOIA_CB_FIXUP_DROPPED: qDebug() << "Fixup dropped"; extract_protocol.append(i18n("Fixup dropped (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); break; case PARANOIA_CB_FIXUP_DUPED: qDebug() << "Fixup duped"; extract_protocol.append(i18n("Fixup duped (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); break; case PARANOIA_CB_READERR: qDebug() << "Read error"; if (!read_error) { read_error = true; emit warning(i18n("Read error detected (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); } extract_protocol.append(i18n("READ ERROR (absolute sector %1, relative sector %2, track time pos %3:%4)", sector, current_sector, tp_min, tp_sec)); break; } } diff --git a/utils/cddaparanoia.cpp b/utils/cddaparanoia.cpp index c31cdfb..2f0ba78 100644 --- a/utils/cddaparanoia.cpp +++ b/utils/cddaparanoia.cpp @@ -1,366 +1,366 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "cddaparanoia.h" #include /* some of this code in here is based on k3b 0.8.x sourcecode */ CDDAParanoia::CDDAParanoia(QObject *parent) : QObject(parent) { Q_UNUSED(parent); - paranoia = NULL; - paranoia_drive = NULL; + paranoia = nullptr; + paranoia_drive = nullptr; setNeverSkip(true); setMaxRetries(20); setParanoiaMode(3); } CDDAParanoia::~CDDAParanoia() { _paranoia_free(); } bool CDDAParanoia::setDevice(const QString &device) { if ((device.isEmpty() && (_device.isEmpty()))) _device = "/dev/cdrom"; if (!device.isEmpty()) _device = device; if (!_paranoia_init()) { qDebug() << "Internal device error."; emit error(i18n("Internal device error."), i18n("Check your device. Is it really \"%1\"? If so also check your permissions on \"%1\".", _device)); return false; } return true; } QString CDDAParanoia::device() const { return _device; } void CDDAParanoia::setParanoiaMode(int mode) { mutex.lock(); // from cdrdao 1.1.7 paranoia_mode = PARANOIA_MODE_FULL ^ PARANOIA_MODE_NEVERSKIP; switch (mode) { case 0: paranoia_mode = PARANOIA_MODE_DISABLE; break; case 1: paranoia_mode |= PARANOIA_MODE_OVERLAP; paranoia_mode &= ~PARANOIA_MODE_VERIFY; break; case 2: paranoia_mode &= ~(PARANOIA_MODE_SCRATCH | PARANOIA_MODE_REPAIR); break; } if (paranoia_never_skip) paranoia_mode |= PARANOIA_MODE_NEVERSKIP; if (paranoia) paranoia_modeset(paranoia, paranoia_mode); mutex.unlock(); } void CDDAParanoia::setNeverSkip(bool b) { paranoia_never_skip = b; setParanoiaMode(paranoia_mode); } void CDDAParanoia::setMaxRetries(int m) { paranoia_max_retries = m; } qint16 *CDDAParanoia::paranoiaRead(void (*callback)(long, int)) { if (paranoia) { mutex.lock(); int16_t *data = paranoia_read_limited(paranoia, callback, paranoia_max_retries); mutex.unlock(); return data; } - return 0; + return nullptr; } int CDDAParanoia::paranoiaSeek(long sector, int mode) { if (paranoia) { mutex.lock(); long pos = paranoia_seek(paranoia, sector, mode); mutex.unlock(); return pos; } return -1; } int CDDAParanoia::firstSectorOfTrack(int track) { if (paranoia_drive) { mutex.lock(); long first_sector = cdda_track_firstsector(paranoia_drive, track); mutex.unlock(); return first_sector; } return -1; } int CDDAParanoia::lastSectorOfTrack(int track) { if (paranoia_drive) { mutex.lock(); long last_sector = cdda_track_lastsector(paranoia_drive, track); mutex.unlock(); return last_sector; } return -1; } int CDDAParanoia::firstSectorOfDisc() { if (paranoia_drive) { mutex.lock(); long first_sector = cdda_disc_firstsector(paranoia_drive); mutex.unlock(); return first_sector; } return -1; } int CDDAParanoia::lastSectorOfDisc() { if (paranoia_drive) { mutex.lock(); long last_sector = cdda_disc_lastsector(paranoia_drive); mutex.unlock(); return last_sector; } return -1; } void CDDAParanoia::sampleOffset(const int offset) { int sample_offset = offset; // Hack from cdda paranoia if (paranoia_drive) { mutex.lock(); int toc_offset = 0; toc_offset += sample_offset / 588; sample_offset %= 588; if (sample_offset < 0) { sample_offset += 588; toc_offset--; } for (int i = 0; i < paranoia_drive->tracks + 1; ++i) paranoia_drive->disc_toc[i].dwStartSector += toc_offset; mutex.unlock(); } } int CDDAParanoia::numOfTracks() { if (paranoia_drive) return (paranoia_drive->tracks < 0) ? 0 : paranoia_drive->tracks; return 0; } int CDDAParanoia::numOfAudioTracks() { if (numOfTracks() > 0) { int j = 0; for (int i = 1; i <= numOfTracks(); i++) { if (isAudioTrack(i)) j++; } return j; } return 0; } int CDDAParanoia::length() { return numOfFrames() / 75; } int CDDAParanoia::numOfFrames() { if (numOfTracks() > 0) { if (paranoia_drive) return cdda_disc_lastsector(paranoia_drive); } return 0; } int CDDAParanoia::lengthOfAudioTracks() { return numOfFramesOfAudioTracks() / 75; } int CDDAParanoia::numOfFramesOfAudioTracks() { if (numOfTracks() > 0) { int frames = 0; for (int i = 1; i <= numOfTracks(); ++i) { if (isAudioTrack(i)) frames += numOfFramesOfTrack(i); } return frames; } return 0; } int CDDAParanoia::numOfSkippedFrames(int n) { if (numOfTracks() > 0) { if (n < 1) n = 1; if (n > numOfTracks()) n = numOfTracks(); int frames = 0; for (int i = 1; i < n; ++i) { if (!isAudioTrack(i)) frames += numOfFramesOfTrack(i); } return frames; } return 0; } int CDDAParanoia::lengthOfTrack(int n) { if (numOfTracks() > 0) { return numOfFramesOfTrack(n) / 75; } return 0; } int CDDAParanoia::numOfFramesOfTrack(int n) { if (numOfTracks() > 0) { if (n < 1) n = 1; if (n > numOfTracks()) n = numOfTracks(); if (n == numOfTracks()) { return numOfFrames() - paranoia_drive->disc_toc[n - 1].dwStartSector; } else { return paranoia_drive->disc_toc[n].dwStartSector - paranoia_drive->disc_toc[n - 1].dwStartSector; } } return 0; } double CDDAParanoia::sizeOfTrack(int n) { if (numOfTracks() > 0) { double frame_size = (double)(numOfFramesOfTrack(n)); if (isAudioTrack(n)) { return (frame_size * 2352.0f) / (1024.0f * 1024.0f); } else { return (frame_size * 2048.0f) / (1024.0f * 1024.0f); } } return 0.0f; } int CDDAParanoia::frameOffsetOfTrack(int n) { if (numOfTracks() > 0) { return paranoia_drive->disc_toc[n - 1].dwStartSector; } return 0; } bool CDDAParanoia::isAudioTrack(int n) { if (paranoia_drive) return IS_AUDIO(paranoia_drive, n - 1); return true; } QList CDDAParanoia::discSignature(const qint32 pregap) { QList result; for (int i = 1; i <= numOfTracks() + 1; ++i) result.append(frameOffsetOfTrack(i) + pregap); return result; } void CDDAParanoia::reset() { _paranoia_init(); } bool CDDAParanoia::_paranoia_init() { mutex.lock(); _paranoia_free(); - paranoia_drive = cdda_identify(_device.toAscii().data(), 0, 0); - if (paranoia_drive == 0) { + paranoia_drive = cdda_identify(_device.toAscii().data(), 0, nullptr); + if (paranoia_drive == nullptr) { mutex.unlock(); qDebug() << "Failed to find device."; return false; } // cdda_cdda_verbose_set(_drive, 1, 1); cdda_open(paranoia_drive); paranoia = paranoia_init(paranoia_drive); - if (paranoia == 0) { + if (paranoia == nullptr) { _paranoia_free(); mutex.unlock(); qDebug() << "Failed to init device."; return false; } mutex.unlock(); return true; } void CDDAParanoia::_paranoia_free() { // mutex.lock(); if (paranoia) { paranoia_free(paranoia); - paranoia = 0; + paranoia = nullptr; } if (paranoia_drive) { cdda_close(paranoia_drive); - paranoia_drive = 0; + paranoia_drive = nullptr; } // mutex.unlock(); } diff --git a/utils/cddaparanoia.h b/utils/cddaparanoia.h index 121a8d0..5f31ba7 100644 --- a/utils/cddaparanoia.h +++ b/utils/cddaparanoia.h @@ -1,120 +1,120 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CDDAPARANOIA_HEADER #define CDDAPARANOIA_HEADER #include #include #include #include extern "C" { #include #include } // from cdda_interface.h #define CD_FRAMESIZE_RAW 2352 #define CDROM_FRAMESIZE_RAW 2048 #define PREGAP 150 // from cdda_paranoia.h #define PARANOIA_CB_READ 0 #define PARANOIA_CB_VERIFY 1 #define PARANOIA_CB_FIXUP_EDGE 2 #define PARANOIA_CB_FIXUP_ATOM 3 #define PARANOIA_CB_SCRATCH 4 #define PARANOIA_CB_REPAIR 5 #define PARANOIA_CB_SKIP 6 #define PARANOIA_CB_DRIFT 7 #define PARANOIA_CB_BACKOFF 8 #define PARANOIA_CB_OVERLAP 9 #define PARANOIA_CB_FIXUP_DROPPED 10 #define PARANOIA_CB_FIXUP_DUPED 11 #define PARANOIA_CB_READERR 12 class CDDAParanoia : public QObject { Q_OBJECT public: - explicit CDDAParanoia(QObject *parent = 0); + explicit CDDAParanoia(QObject *parent = nullptr); ~CDDAParanoia() override; bool setDevice(const QString &device = "/dev/cdrom"); QString device() const; void setParanoiaMode(int mode); /* default: 3 */ void setNeverSkip(bool b); void setMaxRetries(int m); /* default: 20 */ qint16 *paranoiaRead(void (*callback)(long, int)); int paranoiaSeek(long sector, int mode); int firstSectorOfTrack(int track); int lastSectorOfTrack(int track); int firstSectorOfDisc(); int lastSectorOfDisc(); void sampleOffset(const int offset); int numOfTracks(); int numOfAudioTracks(); int length(); int numOfFrames(); // whole disc int lengthOfAudioTracks(); // length of all audio tracks int numOfFramesOfAudioTracks(); /*sum skipped (because it is an audio track) frames usually used to calculate overall percent*/ int numOfSkippedFrames(int n = 100); int lengthOfTrack(int n); int numOfFramesOfTrack(int n); double sizeOfTrack(int n); // in MiB int frameOffsetOfTrack(int n); bool isAudioTrack(int n); // First element is first track after lead-in, list of offsets, last element offset of lead-out // PREGAP is 150 frames = 2 seconds QList discSignature(const qint32 pregap = PREGAP); void reset(); signals: void error(const QString &message, const QString &details = QString()); private: QMutex mutex; QString _device; cdrom_drive *paranoia_drive; cdrom_paranoia *paranoia; int paranoia_mode; bool paranoia_never_skip; int paranoia_max_retries; bool _paranoia_init(); void _paranoia_free(); }; #endif diff --git a/utils/coverfetcher.h b/utils/coverfetcher.h index d54cbee..c5d2c88 100644 --- a/utils/coverfetcher.h +++ b/utils/coverfetcher.h @@ -1,98 +1,98 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COVERFETCHER_HEADER #define COVERFETCHER_HEADER #include #include #include #include #include #include #include class CoverFetcher : public QObject { Q_OBJECT public: - explicit CoverFetcher(QObject *parent = 0); + explicit CoverFetcher(QObject *parent = nullptr); ~CoverFetcher() override; void startFetchThumbnails(const QString &searchstring, const int fetchNo = 8); void stopFetchThumbnails(); void startFetchCover(const int no); const QByteArray thumbnail(int index); const QString caption(int index); const QString tbnid(int index); inline int count() { return cover_names.count(); } enum Status { NOS, SEARCHING, FETCHING_THUMBNAIL, FETCHING_COVER }; inline Status status() const { return _status; } signals: void fetchedThumbnail(const QByteArray &thumbnail, const QString &caption, int no); void allCoverThumbnailsFetched(); void fetchedCover(const QByteArray &cover); void nothingFetched(); void statusChanged(CoverFetcher::Status status); void error(const QString &description, const QString &solution = QString()); void warning(const QString &description); void info(const QString &description); private slots: void fetched_html_data(KJob *job); void fetched_external_ip(KJob *job); private: int fetch_no; QStringList cover_urls_thumbnails; QStringList cover_urls; QStringList cover_names; QStringList cover_tbnids; QList cover_thumbnails; void clear() { cover_thumbnails.clear(); } KIO::TransferJob *job; Status _status; int f_i; QString external_ip; QString search_string; void parse_html_response(const QString &html); bool fetch_cover_thumbnail(); bool fetch_cover(const int no); }; #endif diff --git a/utils/encoderassistant.h b/utils/encoderassistant.h index 396b685..3b0cee9 100644 --- a/utils/encoderassistant.h +++ b/utils/encoderassistant.h @@ -1,190 +1,190 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ENCODERASSISTANT_H #define ENCODERASSISTANT_H #include #include #include #include #include #include "utils/parameters.h" #include "utils/patternparser.h" #define ENCODER_LAME_SUFFIX_KEY "suffix" #define ENCODER_LAME_PRESET_KEY "preset" #define ENCODER_LAME_PRESET_MEDIUM 0 #define ENCODER_LAME_PRESET_STANDARD 1 #define ENCODER_LAME_PRESET_EXTREME 2 #define ENCODER_LAME_PRESET_INSANE 3 #define ENCODER_LAME_PRESET_CUSTOM 4 #define ENCODER_LAME_CBR_KEY "cbr" #define ENCODER_LAME_BITRATE_KEY "bitrate" #define ENCODER_LAME_EMBED_COVER_KEY "embed_cover" #define ENCODER_OGGENC_SUFFIX_KEY "suffix" #define ENCODER_OGGENC_QUALITY_KEY "quality" #define ENCODER_OGGENC_MINBITRATE_KEY "minbitrate" #define ENCODER_OGGENC_MINBITRATE_VALUE_KEY "minbitrate_value" #define ENCODER_OGGENC_MAXBITRATE_KEY "maxbitrate" #define ENCODER_OGGENC_MAXBITRATE_VALUE_KEY "maxbitrate_value" #define ENCODER_FLAC_SUFFIX_KEY "suffix" #define ENCODER_FLAC_COMPRESSION_KEY "compression" #define ENCODER_FLAC_EMBED_COVER_KEY "embed_cover" #define ENCODER_FAAC_SUFFIX_KEY "suffix" #define ENCODER_FAAC_QUALITY_KEY "quality" #define ENCODER_WAVE_SUFFIX_KEY "suffix" #define ENCODER_CUSTOM_SUFFIX_KEY "suffix" #define ENCODER_CUSTOM_COMMAND_PATTERN_KEY "command_pattern" /******************/ /* default values */ /******************/ #define ENCODER_LAME_NAME i18n("MP3") #define ENCODER_LAME_ENCODER_NAME "LAME" #define ENCODER_LAME_ICON "audio-mpeg" #define ENCODER_LAME_BIN "lame" #define ENCODER_LAME_VERSION_PARA "--version" #define ENCODER_LAME_SUFFIX "mp3" #define ENCODER_LAME_MAX_EMBED_COVER_SIZE 128 * 1024 /* preset normal quality */ #define ENCODER_LAME_PRESET 1 #define ENCODER_LAME_CBR "false" #define ENCODER_LAME_BITRATE 192 #define ENCODER_LAME_EMBED_COVER "false" /* preset mobile quality */ #define ENCODER_LAME_PRESET_M 4 #define ENCODER_LAME_CBR_M "false" #define ENCODER_LAME_BITRATE_M 128 #define ENCODER_LAME_EMBED_COVER_M "false" /* preset extreme quality */ #define ENCODER_LAME_PRESET_X 2 #define ENCODER_LAME_CBR_X "false" #define ENCODER_LAME_BITRATE_X 192 #define ENCODER_LAME_EMBED_COVER_X "false" /* tag helper for lame */ #define ENCODER_LAME_HELPER_TAG "eyeD3" #define ENCODER_LAME_HELPER_TAG_VERSION_PARA "--version" #define ENCODER_OGGENC_NAME i18n("Ogg Vorbis") #define ENCODER_OGGENC_ENCODER_NAME "OGGENC" #define ENCODER_OGGENC_ICON "audio-x-vorbis+ogg" #define ENCODER_OGGENC_BIN "oggenc" #define ENCODER_OGGENC_VERSION_PARA "--version" #define ENCODER_OGGENC_SUFFIX "ogg" /* preset normal quality */ #define ENCODER_OGGENC_QUALITY 4 #define ENCODER_OGGENC_MINBITRATE true #define ENCODER_OGGENC_MINBITRATE_VALUE 80 #define ENCODER_OGGENC_MAXBITRATE false #define ENCODER_OGGENC_MAXBITRATE_VALUE 256 /* preset mobile quality */ #define ENCODER_OGGENC_QUALITY_M 2 #define ENCODER_OGGENC_MINBITRATE_M false #define ENCODER_OGGENC_MINBITRATE_VALUE_M 80 #define ENCODER_OGGENC_MAXBITRATE_M true #define ENCODER_OGGENC_MAXBITRATE_VALUE_M 224 /* preset extreme quality */ #define ENCODER_OGGENC_QUALITY_X 6 #define ENCODER_OGGENC_MINBITRATE_X false #define ENCODER_OGGENC_MINBITRATE_VALUE_X 80 #define ENCODER_OGGENC_MAXBITRATE_X false #define ENCODER_OGGENC_MAXBITRATE_VALUE_X 256 #define ENCODER_FLAC_NAME i18n("FLAC (Lossless)") #define ENCODER_FLAC_ENCODER_NAME "FLAC" #define ENCODER_FLAC_ICON "audio-x-flac" #define ENCODER_FLAC_BIN "flac" #define ENCODER_FLAC_VERSION_PARA "-v" #define ENCODER_FLAC_SUFFIX "flac" #define ENCODER_FLAC_COMPRESSION 5 #define ENCODER_FLAC_EMBED_COVER "true" #define ENCODER_FAAC_NAME i18n("MP4 (AAC)") #define ENCODER_FAAC_ENCODER_NAME "FAAC" #define ENCODER_FAAC_ICON "audio-mp4" #define ENCODER_FAAC_BIN "faac" #define ENCODER_FAAC_VERSION_PARA "--help" #define ENCODER_FAAC_SUFFIX "mp4" /* preset normal quality */ #define ENCODER_FAAC_QUALITY 150 /* preset mobile quality */ #define ENCODER_FAAC_QUALITY_M 110 /* preset extreme quality */ #define ENCODER_FAAC_QUALITY_X 300 #define ENCODER_WAVE_NAME i18n("WAVE (Raw Uncompressed)") #define ENCODER_WAVE_ENCODER_NAME "WAVE" #define ENCODER_WAVE_ICON "audio-x-wav" #define ENCODER_WAVE_BIN "mv" #define ENCODER_WAVE_VERSION_PARA "--help" #define ENCODER_WAVE_SUFFIX "wav" #define ENCODER_CUSTOM_NAME i18n("Custom") #define ENCODER_CUSTOM_ENCODER_NAME i18n("Custom") #define ENCODER_CUSTOM_ICON "audio-x-generic" #define ENCODER_CUSTOM_BIN "" #define ENCODER_CUSTOM_VERSION_PARA "" #define ENCODER_CUSTOM_SUFFIX "" #define ENCODER_CUSTOM_COMMAND_PATTERN "" #define ENCODER_NUM 6 namespace EncoderAssistant { enum Encoder { LAME = 0, OGGENC, FLAC, FAAC, WAVE, CUSTOM, NUM }; const QString name(const Encoder encoder); const QString encoderName(const Encoder encoder); const QString icon(const Encoder encoder); bool available(const Encoder encoder); -bool canEmbedCover(const Encoder encoder, int *maxCoverSize = NULL); +bool canEmbedCover(const Encoder encoder, int *maxCoverSize = nullptr); const QString version(const Encoder encoder); long versionNumber(const Encoder encoder); const QString pattern(const Encoder encoder, const Parameters ¶meters); enum Quality { MOBILE = 0, NORMAL, EXTREME }; Parameters stdParameters(const Encoder encoder, const Quality quality); const QMap encoderList(); const QMap availableEncoderNameList(); const QMap availableEncoderNameListWithVersions(); }; #endif diff --git a/utils/encoderwrapper.h b/utils/encoderwrapper.h index 9891367..501e830 100644 --- a/utils/encoderwrapper.h +++ b/utils/encoderwrapper.h @@ -1,92 +1,92 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ENCODERWRAPPER_HEADER #define ENCODERWRAPPER_HEADER #include #include #include #include #include "utils/cachedimage.h" #include "utils/patternparser.h" class EncoderWrapper : public QObject { Q_OBJECT public: - explicit EncoderWrapper(QObject *parent = 0, const QString &commandPattern = "", const QString &encoderName = "", const bool deleteFractionFiles = true); + explicit EncoderWrapper(QObject *parent = nullptr, const QString &commandPattern = "", const QString &encoderName = "", const bool deleteFractionFiles = true); ~EncoderWrapper() override; bool isProcessing(); const QStringList &protocol(); public slots: bool encode(int n, int cdno, int trackoffset, int nooftracks, const QString &artist, const QString &album, const QString &tartist, const QString &ttitle, const QString &genre, const QString &date, const QString &suffix, CachedImage *cover, bool fat_compatible, const QString &tmppath, const QString &input, const QString &output); void cancel(); private slots: void parseOutput(); void processFinished(int exitCode, QProcess::ExitStatus exitStatus); void processError(QProcess::ProcessError err); signals: void progress(int percent_of_track); void finished(); void error(const QString &message, const QString &details = QString()); void warning(const QString &message); void info(const QString &message); private: QString command_pattern; QString encoder_name; bool delete_fraction_files; QString encoder; QStringList _protocol; QString processing_filename; bool termination; int processing; KProcess proc; int not_found_counter; }; #endif diff --git a/utils/error.h b/utils/error.h index 3407008..2866737 100644 --- a/utils/error.h +++ b/utils/error.h @@ -1,78 +1,78 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ERROR_H #define ERROR_H class Error { public: enum ErrorType { ERROR, WARNING }; - explicit Error(const QString &message = "", const QString &details = "", const ErrorType errorType = Error::ERROR, QObject *parent = 0) + explicit Error(const QString &message = "", const QString &details = "", const ErrorType errorType = Error::ERROR, QObject *parent = nullptr) { Q_UNUSED(parent); m = message; d = details; e = errorType; } Error(const Error &other) { m = other.m; d = other.d; e = other.e; } Error &operator=(const Error &other) { m = other.m; d = other.d; e = other.e; return *this; } ~Error() { } ErrorType errorType() const { return e; } bool isValid() const { return (!m.isEmpty()); } const QString message() const { return m; } const QString details() const { return d; } private: ErrorType e; QString m; QString d; }; typedef QList ErrorList; #endif diff --git a/utils/hashlist.cpp b/utils/hashlist.cpp index 148e709..0a8759c 100644 --- a/utils/hashlist.cpp +++ b/utils/hashlist.cpp @@ -1,78 +1,78 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "hashlist.h" Hashlist::Hashlist() { } const QStringList Hashlist::getSFV(const QStringList &filenames) { QStringList list; for (int i = 0; i < filenames.count(); ++i) { // uses mmap for performance int fd = open(filenames.at(i).toUtf8().constData(), O_RDONLY); if (fd == -1) continue; quint64 size = lseek(fd, 0, SEEK_END); - char *t_data = (char *)mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); + char *t_data = (char *)mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); CRC32 crc32; crc32.update((const unsigned char *)t_data, (int)lseek(fd, 0, SEEK_END)); QFileInfo info(filenames.at(i)); list << info.fileName() + ' ' + QString("%1").arg(crc32.result(), 0, 16); close(fd); } return list; } const QStringList Hashlist::getMD5(const QStringList &filenames) { QStringList list; for (int i = 0; i < filenames.count(); ++i) { QFile file(filenames.at(i)); if (!file.exists()) continue; if (!file.open(QFile::ReadOnly)) continue; QCryptographicHash md5sum(QCryptographicHash::Md5); QByteArray buf; while (!file.atEnd()) { buf = file.read(16 * 1024); md5sum.addData(buf); } QFileInfo info(filenames.at(i)); list << QString("%1").arg(QString(md5sum.result().toHex())) + " " + info.fileName(); file.close(); } return list; } diff --git a/utils/patternparser.cpp b/utils/patternparser.cpp index 3ff34eb..7183b3b 100644 --- a/utils/patternparser.cpp +++ b/utils/patternparser.cpp @@ -1,779 +1,779 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "patternparser.h" #include #include SaxHandler::SaxHandler() : QXmlDefaultHandler() { trackno = 1; cdno = 0; trackoffset = 0; fat32compatible = false; discid = 0; size = 0; length = 0; nooftracks = 0; is_filename_pattern = false; is_command_pattern = false; is_simple_pattern = false; is_text_pattern = false; - cover = NULL; + cover = nullptr; /*TEMP*/ found_suffix = false; } SaxHandler::~SaxHandler() { } bool SaxHandler::startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts) { Q_UNUSED(namespaceURI); Q_UNUSED(localName); if (qName == VAR_FILENAME_PATTERN) { is_filename_pattern = true; return true; } if (qName == VAR_COMMAND_PATTERN) { is_command_pattern = true; return true; } if (qName == VAR_SIMPLE_PATTERN) { is_simple_pattern = true; return true; } if (qName == VAR_TEXT_PATTERN) { is_text_pattern = true; return true; } p_element.clear(); if (qName == VAR_ALBUM_ARTIST) { if ((is_filename_pattern) || (is_simple_pattern)) { QString s = artist; if ((fat32compatible) || (IS_TRUE(atts.value("fat32compatible")))) s = make_fat32_compatible(s); else s = make_compatible(s); if ((replacespaceswithunderscores) || (IS_TRUE(atts.value("underscores")))) s = replace_spaces_with_underscores(s); // int QString::toInt(bool *ok, int base) const // If a conversion error occurs, *\a{ok} is set to \c false; otherwise // *\a{ok} is set to \c true. // http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/tools/qstring.cpp#n6418 bool ok; int left = atts.value("left").toInt(&ok); if ((ok) && (left > 0)) s = s.left(left); if (IS_TRUE(atts.value("replace_char_list"))) s = replace_char_list(atts, s); if (IS_TRUE(atts.value("lowercase"))) s = s.toLower(); else if (IS_TRUE(atts.value("uppercase"))) s = s.toUpper(); p_element += s; } else if (is_command_pattern) { p_element += make_compatible_2(artist); } else { p_element += artist; } } if (qName == VAR_ALBUM_TITLE) { if ((is_filename_pattern) || (is_simple_pattern)) { QString s = title; if ((fat32compatible) || (IS_TRUE(atts.value("fat32compatible")))) s = make_fat32_compatible(s); else s = make_compatible(s); if ((replacespaceswithunderscores) || (IS_TRUE(atts.value("underscores")))) s = replace_spaces_with_underscores(s); bool ok; int left = atts.value("left").toInt(&ok); if ((ok) && (left > 0)) s = s.left(left); if (IS_TRUE(atts.value("replace_char_list"))) s = replace_char_list(atts, s); if (IS_TRUE(atts.value("lowercase"))) s = s.toLower(); else if (IS_TRUE(atts.value("uppercase"))) s = s.toUpper(); p_element += s; } else if (is_command_pattern) { p_element += make_compatible_2(title); } else { p_element += title; } } if (qName == VAR_DATE) { if ((is_filename_pattern) || (is_simple_pattern)) { QString s = date; if ((fat32compatible) || (IS_TRUE(atts.value("fat32compatible")))) s = make_fat32_compatible(s); else s = make_compatible(s); if ((replacespaceswithunderscores) || (IS_TRUE(atts.value("underscores")))) s = replace_spaces_with_underscores(s); bool ok; int left = atts.value("left").toInt(&ok); if ((ok) && (left > 0)) s = s.left(left); if (IS_TRUE(atts.value("replace_char_list"))) s = replace_char_list(atts, s); if (IS_TRUE(atts.value("lowercase"))) s = s.toLower(); else if (IS_TRUE(atts.value("uppercase"))) s = s.toUpper(); p_element += s; } else if (is_command_pattern) { p_element += make_compatible_2(date); } else { p_element += date; } } if (qName == VAR_GENRE) { if ((is_filename_pattern) || (is_simple_pattern)) { QString s = genre; if ((fat32compatible) || (IS_TRUE(atts.value("fat32compatible")))) s = make_fat32_compatible(s); else s = make_compatible(s); if ((replacespaceswithunderscores) || (IS_TRUE(atts.value("underscores")))) s = replace_spaces_with_underscores(s); bool ok; int left = atts.value("left").toInt(&ok); if ((ok) && (left > 0)) s = s.left(left); if (IS_TRUE(atts.value("replace_char_list"))) s = replace_char_list(atts, s); if (IS_TRUE(atts.value("lowercase"))) s = s.toLower(); else if (IS_TRUE(atts.value("uppercase"))) s = s.toUpper(); p_element += s; } else if (is_command_pattern) { p_element += make_compatible_2(genre); } else { p_element += genre; } } if (qName == VAR_ENCODER) { p_element += encoder; } if ((is_filename_pattern) || (is_command_pattern) || (is_simple_pattern)) { if (qName == VAR_CD_NO) { if (cdno > 0) { bool ok; int l = atts.value("length").toInt(&ok); QChar fc = '0'; if (!atts.value("fillchar").isEmpty()) fc = atts.value("fillchar").at(0); if (ok) p_element += QString("%1").arg(cdno, l, 10, fc); else p_element += QString("%1").arg(cdno); } } } if ((is_filename_pattern) || (is_command_pattern)) { if (qName == VAR_TRACK_ARTIST) { if (is_filename_pattern) { QString s = tartist; if ((fat32compatible) || (IS_TRUE(atts.value("fat32compatible")))) s = make_fat32_compatible(s); else s = make_compatible(s); if ((replacespaceswithunderscores) || (IS_TRUE(atts.value("underscores")))) s = replace_spaces_with_underscores(s); bool ok; int left = atts.value("left").toInt(&ok); if ((ok) && (left > 0)) s = s.left(left); if (IS_TRUE(atts.value("lowercase"))) s = s.toLower(); else if (IS_TRUE(atts.value("uppercase"))) s = s.toUpper(); if (IS_TRUE(atts.value("replace_char_list"))) s = replace_char_list(atts, s); p_element += s; } else if (is_command_pattern) { p_element += make_compatible_2(tartist); } else { p_element += tartist; } } if (qName == VAR_TRACK_TITLE) { if (is_filename_pattern) { QString s = ttitle; if ((fat32compatible) || (IS_TRUE(atts.value("fat32compatible")))) s = make_fat32_compatible(s); else s = make_compatible(s); if ((replacespaceswithunderscores) || (IS_TRUE(atts.value("underscores")))) s = replace_spaces_with_underscores(s); bool ok; int left = atts.value("left").toInt(&ok); if ((ok) && (left > 0)) s = s.left(left); if (IS_TRUE(atts.value("replace_char_list"))) s = replace_char_list(atts, s); if (IS_TRUE(atts.value("lowercase"))) s = s.toLower(); else if (IS_TRUE(atts.value("uppercase"))) s = s.toUpper(); p_element += s; } else if (is_command_pattern) { p_element += make_compatible_2(ttitle); } else { p_element += ttitle; } } if (qName == VAR_TRACK_NO) { int t; if (trackoffset > 1) t = trackno + trackoffset; else t = trackno; bool ok; int l = atts.value("length").toInt(&ok); QChar fc = '0'; if (!atts.value("fillchar").isEmpty()) fc = atts.value("fillchar").at(0); if (ok) { p_element += QString("%1").arg(t, l, 10, fc); } else { if (_2digitstracknum) { p_element += QString("%1").arg(t, 2, 10, QChar('0')); } else { p_element += QString("%1").arg(t); } } } } if ((is_filename_pattern) || (is_simple_pattern)) { if (qName == VAR_SUFFIX) { /*TEMP*/ found_suffix = true; p_element += suffix; } } if (is_command_pattern) { if (qName == VAR_INPUT_FILE) p_element += "\"" + input + "\""; if (qName == VAR_OUTPUT_FILE) p_element += "\"" + output + "\""; if (qName == VAR_COVER_FILE) { QString format = STANDARD_EMBED_COVER_FORMAT; if (!atts.value("format").isEmpty()) format = atts.value("format"); // cover set by setCover if ((cover) && (!cover->supportedFormats().contains(format.toAscii().toLower()))) format = STANDARD_EMBED_COVER_FORMAT; QString filename; bool stop = false; if (demomode) { filename = tmppath + "audexcover.123." + format.toLower(); } else { int x = -1; int y = -1; bool ok; if (!atts.value("x").isEmpty()) { // when *ok is false, QString::toInt() often return 0 x = atts.value("x").toInt(&ok); if (!ok) x = -1; } if (!atts.value("y").isEmpty()) { y = atts.value("y").toInt(&ok); if (!ok) y = -1; } QByteArray ba = QCryptographicHash::hash(QString(artist + title + date + QString("%1").arg(x * y) + format).toUtf8(), QCryptographicHash::Md5); QString mda5 = ba.toHex(); if (!stop) filename = tmppath + "cover." + QString("%1").arg(mda5) + '.' + format.toLower(); QFileInfo finfo(filename); if ((!finfo.exists()) && (!stop)) { bool success; if ((!cover) || ((cover) && (cover->isEmpty()))) { if (IS_TRUE(atts.value("usenocover"))) { QImage c = QImage(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QString("audex/images/nocover.png"))); if ((x != -1) && (y != -1)) { c = c.scaled(x, y, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } success = c.save(filename, format.toAscii()); } else { stop = true; } } else { success = cover->save(filename, QSize(x, y)); } if (!stop) { if (!success) { qDebug() << "WARNING! Could not create temporary cover file" << filename; } else { qDebug() << "Successfully created temporary cover file" << filename << "(" << QFile(filename).size() / 1024 << "KiB)"; } } } } if (!stop) { p_element = "\"" + filename + "\""; } } } if (is_text_pattern) { if (qName == VAR_CD_SIZE) { QChar iec; if (!atts.value("iec").isEmpty()) iec = atts.value("iec").at(0); if ((iec != 'b') && (iec != 'k') && (iec != 'm') && (iec != 'g')) iec = 'm'; bool ok; int p = atts.value("precision").toInt(&ok); if (!ok) p = 2; if (iec == 'b') p_element += QString("%1").arg(size, 0, 'f', p); else if (iec == 'k') p_element += QString("%1").arg(size / 1024.0f, 0, 'f', p); else if (iec == 'm') p_element += QString("%1").arg(size / (1024.0f * 1024.0f), 0, 'f', p); else if (iec == 'g') p_element += QString("%1").arg(size / (1024.0f * 1024.0f * 1024.0f), 0, 'f', p); } if (qName == VAR_CD_LENGTH) p_element += QString("%1:%2").arg(length / 60, 2, 10, QChar('0')).arg(length % 60, 2, 10, QChar('0')); if (qName == VAR_TODAY) { QString format; if (!atts.value("format").isEmpty()) format = atts.value("format"); if (format.isEmpty()) { p_element += QString("%1").arg(QDate::currentDate().toString()); } else { p_element += QString("%1").arg(QDate::currentDate().toString(format)); } } if (qName == VAR_NOW) { QString format; if (!atts.value("format").isEmpty()) format = atts.value("format"); if (format.isEmpty()) { p_element += QString("%1").arg(QDateTime::currentDateTime().toString()); } else { p_element += QString("%1").arg(QDateTime::currentDateTime().toString(format)); } } if (qName == VAR_LINEBREAK) p_element += '\n'; if (qName == VAR_DISCID) { bool ok; int base = atts.value("base").toInt(&ok); if (!ok) base = 16; p_element += QString("%1").arg(discid, 0, base); } } if (qName == VAR_NO_OF_TRACKS) p_element += QString("%1").arg(nooftracks); if (qName == VAR_AUDEX) p_element += QString("Audex Version %1").arg(AUDEX_VERSION); if ((!p_element.isEmpty()) && (is_command_pattern)) { QString pre = atts.value("pre"); QString post = atts.value("post"); p_text += pre + p_element + post; } else { p_text += p_element; } return true; } bool SaxHandler::endElement(const QString &namespaceURI, const QString &localName, const QString &qName) { Q_UNUSED(namespaceURI); Q_UNUSED(localName); if (qName == VAR_FILENAME_PATTERN) { is_filename_pattern = false; p_text.replace("//", "/"); p_text = p_text.simplified(); return true; } if (qName == VAR_COMMAND_PATTERN) { is_command_pattern = false; p_text.replace("//", "/"); p_text = p_text.simplified(); return true; } if (qName == VAR_SIMPLE_PATTERN) { is_simple_pattern = false; p_text.replace("//", "/"); p_text = p_text.simplified(); return true; } if (qName == VAR_TEXT_PATTERN) { is_text_pattern = false; return true; } return true; } bool SaxHandler::characters(const QString &ch) { p_text += ch; return true; } bool SaxHandler::fatalError(const QXmlParseException &exception) { qDebug() << QString("XML pattern parse error: Column %1 (%2)").arg(exception.columnNumber()).arg(exception.message()); return false; } const QString SaxHandler::make_compatible(const QString &string) { QString s = string; for (int i = 0; i < s.size(); i++) { switch (s[i].toLatin1()) { case '/': case '\\': s[i] = '_'; break; case '"': s[i] = '\''; break; default: break; } } return s; } const QString SaxHandler::make_compatible_2(const QString &string) { QString s = string; s.replace('"', "\\\""); return s; } // remove \ / : * ? " < > | const QString SaxHandler::make_fat32_compatible(const QString &string) { QString s = string; for (int i = 0; i < s.size(); i++) { switch (s[i].toLatin1()) { case '\\': case '/': case ':': case '*': case '?': case '"': case '<': case '>': case '|': s[i] = '_'; break; default: break; } } return s; } const QString SaxHandler::replace_spaces_with_underscores(const QString &string) { QString s = string; s.replace(' ', '_'); return s; } const QString SaxHandler::replace_char_list(const QXmlAttributes &atts, const QString &string) { int i; QString from, to, result; qDebug() << "starting replacement for: " << string; from = atts.value("replace_char_list_from"); to = atts.value("replace_char_list_to"); if (from.count() != to.count()) { qDebug() << "Could not replace if list length are not equal"; return string; } result = string; for (i = 0; i < from.count(); i++) { result.replace(from.at(i), to.at(i)); } qDebug() << "finished: " << result; return result; } PatternParser::PatternParser(QObject *parent) : QObject(parent) { Q_UNUSED(parent); } PatternParser::~PatternParser() { } const QString PatternParser::parseFilenamePattern(const QString &pattern, int trackno, int cdno, int trackoffset, int nooftracks, const QString &artist, const QString &title, const QString &tartist, const QString &ttitle, const QString &date, const QString &genre, const QString &suffix, bool fat32compatible, bool replacespaceswithunderscores, bool _2digitstracknum) { SaxHandler handler; handler.setTrackNo(trackno); handler.setCDNo(cdno); handler.setTrackOffset(trackoffset); handler.setNoOfTracks(nooftracks); handler.setArtist(artist); handler.setTitle(title); handler.setTrackArtist(tartist); handler.setTrackTitle(ttitle); handler.setDate(date); handler.setGenre(genre); handler.setSuffix(suffix); handler.setFAT32Compatible(fat32compatible); handler.setReplaceSpacesWithUnderscores(replacespaceswithunderscores); handler.set2DigitsTrackNum(_2digitstracknum); QXmlInputSource inputSource; inputSource.setData("" + p_xmlize_pattern(pattern) + ""); QXmlSimpleReader reader; reader.setContentHandler(&handler); reader.setErrorHandler(&handler); reader.parse(inputSource); return handler.text(); } const QString PatternParser::parseCommandPattern(const QString &pattern, const QString &input, const QString &output, int trackno, int cdno, int trackoffset, int nooftracks, const QString &artist, const QString &title, const QString &tartist, const QString &ttitle, const QString &date, const QString &genre, const QString &suffix, CachedImage *cover, bool fatcompatible, const QString &tmppath, const QString &encoder, const bool demomode) { SaxHandler handler; handler.setInputFile(input); handler.setOutputFile(output); handler.setTrackNo(trackno); handler.setCDNo(cdno); handler.setTrackOffset(trackoffset); handler.setNoOfTracks(nooftracks); handler.setArtist(artist); handler.setTitle(title); handler.setTrackArtist(tartist); handler.setTrackTitle(ttitle); handler.setDate(date); handler.setGenre(genre); handler.setSuffix(suffix); // cover is initialized! handler.setCover(cover); handler.setFAT32Compatible(fatcompatible); handler.setTMPPath(tmppath); handler.setDemoMode(demomode); handler.set2DigitsTrackNum(false); handler.setEncoder(encoder); QXmlInputSource inputSource; inputSource.setData("" + p_xmlize_pattern(pattern) + ""); QXmlSimpleReader reader; reader.setContentHandler(&handler); reader.setErrorHandler(&handler); reader.parse(inputSource); return handler.text(); } const QString PatternParser::parseSimplePattern(const QString &pattern, int cdno, const int nooftracks, const QString &artist, const QString &title, const QString &date, const QString &genre, const QString &suffix, bool fat32compatible) { SaxHandler handler; handler.setCDNo(cdno); handler.setNoOfTracks(nooftracks); handler.setArtist(artist); handler.setTitle(title); handler.setDate(date); handler.setGenre(genre); handler.setSuffix(suffix); handler.setFAT32Compatible(fat32compatible); handler.setReplaceSpacesWithUnderscores(false); handler.set2DigitsTrackNum(false); QXmlInputSource inputSource; inputSource.setData("" + p_xmlize_pattern(pattern) + ""); QXmlSimpleReader reader; reader.setContentHandler(&handler); reader.setErrorHandler(&handler); reader.parse(inputSource); return handler.text(); } void PatternParser::parseInfoText(QStringList &text, const QString &artist, const QString &title, const QString &date, const QString &genre, const quint32 discid, const qreal size, const int length, const int nooftracks) { SaxHandler handler; handler.setArtist(artist); handler.setTitle(title); handler.setDate(date); handler.setGenre(genre); handler.setDiscid(discid); handler.setSize(size); handler.setLength(length); handler.setNoOfTracks(nooftracks); handler.set2DigitsTrackNum(false); QXmlInputSource inputSource; inputSource.setData("" + p_xmlize_pattern(text.join("\n")) + ""); QXmlSimpleReader reader; reader.setContentHandler(&handler); reader.setErrorHandler(&handler); reader.parse(inputSource); text = handler.text().split('\n'); } const QString PatternParser::p_xmlize_pattern(const QString &pattern) { QString newpattern; QString name; int s = 0; for (int i = 0; i < pattern.length(); ++i) { if (pattern[i] == '&') { newpattern += "&"; continue; } switch (s) { // outside var case 0: if (pattern[i] == '$') { name.clear(); s = 1; continue; } break; // inside var case 1: if (pattern[i] == '{') { s = 3; } else if (pattern[i] == '$') { newpattern += '$'; s = 0; } else { s = 2; name += pattern[i]; } continue; // inside simple var case 2: if (!pattern[i].isLetter()) { if (!name.trimmed().isEmpty()) newpattern += '<' + name + " />"; name.clear(); s = 0; if (pattern[i] == '$') { name.clear(); s = 1; continue; } else { newpattern += pattern[i]; } continue; } name += pattern[i]; continue; // inside extended var case 3: if (pattern[i] == '}') { if (!name.trimmed().isEmpty()) newpattern += '<' + name + " />"; name.clear(); s = 0; continue; } name += pattern[i]; continue; } newpattern += pattern[i]; } // rest at the end? if ((s == 2) && (!name.trimmed().isEmpty())) newpattern += '<' + name + " />"; return newpattern; } diff --git a/utils/patternparser.h b/utils/patternparser.h index 47554c3..7613b81 100644 --- a/utils/patternparser.h +++ b/utils/patternparser.h @@ -1,277 +1,277 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PATTERNPARSER_H #define PATTERNPARSER_H #include #include #include #include #include #include #include #include #include #include "config.h" #include "utils/cachedimage.h" #define IS_TRUE(val) (((val.toLower() == "true") || (val == "1") || (val.toLower() == "on")) ? true : false) #define VAR_FILENAME_PATTERN "filenamepattern" #define VAR_COMMAND_PATTERN "commandpattern" #define VAR_SIMPLE_PATTERN "simplepattern" #define VAR_TEXT_PATTERN "textpattern" #define VAR_ALBUM_ARTIST "artist" #define VAR_ALBUM_TITLE "title" #define VAR_TRACK_ARTIST "tartist" #define VAR_TRACK_TITLE "ttitle" #define VAR_TRACK_NO "trackno" #define VAR_CD_NO "cdno" #define VAR_DATE "date" #define VAR_GENRE "genre" #define VAR_SUFFIX "suffix" #define VAR_ENCODER "encoder" #define VAR_INPUT_FILE "i" #define VAR_OUTPUT_FILE "o" #define VAR_COVER_FILE "cover" #define VAR_DISCID "discid" #define VAR_CD_SIZE "size" #define VAR_CD_LENGTH "length" #define VAR_TODAY "today" #define VAR_NOW "now" #define VAR_LINEBREAK "br" #define VAR_AUDEX "audex" #define VAR_NO_OF_TRACKS "nooftracks" #define STANDARD_EMBED_COVER_FORMAT "jpg" class SaxHandler : public QXmlDefaultHandler { public: SaxHandler(); ~SaxHandler() override; bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts) override; bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName) override; bool characters(const QString &ch) override; bool fatalError(const QXmlParseException &exception) override; void setInputFile(const QString &input) { this->input = input; } void setOutputFile(const QString &output) { this->output = output; } void setTrackNo(const int trackno) { this->trackno = trackno; } void setCDNo(const int cdno) { this->cdno = cdno; } void setTrackOffset(const int trackoffset) { this->trackoffset = trackoffset; } void setArtist(const QString &artist) { this->artist = artist; } void setTitle(const QString &title) { this->title = title; } void setTrackArtist(const QString &tartist) { this->tartist = tartist; } void setTrackTitle(const QString &ttitle) { this->ttitle = ttitle; } void setDate(const QString &date) { this->date = date; } void setGenre(const QString &genre) { this->genre = genre; } void setSuffix(const QString &suffix) { this->suffix = suffix; } void setCover(CachedImage *cover) { this->cover = cover; } void setFAT32Compatible(const bool fat32compatible) { this->fat32compatible = fat32compatible; } void setReplaceSpacesWithUnderscores(const bool replacespaceswithunderscores) { this->replacespaceswithunderscores = replacespaceswithunderscores; } void set2DigitsTrackNum(const bool _2digitstracknum) { this->_2digitstracknum = _2digitstracknum; } void setTMPPath(const QString &tmppath) { this->tmppath = tmppath; } void setDiscid(const quint32 discid) { this->discid = discid; } void setSize(const qreal size) { this->size = size; } void setLength(const int length) { this->length = length; } void setNoOfTracks(const int nooftracks) { this->nooftracks = nooftracks; } void setDemoMode(const bool demomode) { this->demomode = demomode; } void setEncoder(const QString &encoder) { this->encoder = encoder; } inline const QString text() const { return p_text; } private: QString pattern; QString input; QString output; int trackno; int cdno; int trackoffset; QString artist; QString title; QString tartist; QString ttitle; QString date; QString genre; QString suffix; CachedImage *cover; bool fat32compatible; bool replacespaceswithunderscores; bool _2digitstracknum; QString tmppath; quint32 discid; qreal size; int length; int nooftracks; QString encoder; bool demomode; /*TEMP*/ bool found_suffix; QString p_text; QString p_element; bool is_filename_pattern; bool is_command_pattern; bool is_simple_pattern; bool is_text_pattern; const QString make_compatible(const QString &string); const QString make_compatible_2(const QString &string); const QString make_fat32_compatible(const QString &string); const QString replace_spaces_with_underscores(const QString &string); const QString replace_char_list(const QXmlAttributes &atts, const QString &string); }; class PatternParser : public QObject { Q_OBJECT public: - explicit PatternParser(QObject *parent = 0); + explicit PatternParser(QObject *parent = nullptr); ~PatternParser() override; const QString parseFilenamePattern(const QString &pattern, int trackno, int cdno, int trackoffset, int nooftracks, const QString &artist, const QString &title, const QString &tartist, const QString &ttitle, const QString &date, const QString &genre, const QString &suffix, bool fat32compatible, bool replacespaceswithunderscores, bool _2digitstracknum); const QString parseCommandPattern(const QString &pattern, const QString &input, const QString &output, int trackno, int cdno, int trackoffset, int nooftracks, const QString &artist, const QString &title, const QString &tartist, const QString &ttitle, const QString &date, const QString &genre, const QString &suffix, CachedImage *cover, bool fat32compatible, const QString &tmppath, const QString &encoder, const bool demomode = false); const QString parseSimplePattern(const QString &pattern, int cdno, int nooftracks, const QString &artist, const QString &title, const QString &date, const QString &genre, const QString &suffix, bool fat32compatible); void parseInfoText(QStringList &text, const QString &artist, const QString &title, const QString &date, const QString &genre, const quint32 discid, const qreal size, const int length, const int nooftracks); signals: void error(const QString &message, const QString &details = QString()); private: const QString p_xmlize_pattern(const QString &pattern); }; #endif diff --git a/utils/upload.h b/utils/upload.h index 40d9f96..ba4a761 100644 --- a/utils/upload.h +++ b/utils/upload.h @@ -1,50 +1,50 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UPLOAD_H #define UPLOAD_H #include #include #include #include #include #include #include #include class Upload : public QObject { Q_OBJECT public: - explicit Upload(const QUrl &url, QObject *parent = 0); + explicit Upload(const QUrl &url, QObject *parent = nullptr); ~Upload() override; void upload(const QString &targetpath, const QStringList &filelist); signals: void error(const QString &message, const QString &solution = QString()); void warning(const QString &message); void info(const QString &message); private: QUrl base_url; }; #endif diff --git a/widgets/cddaheaderwidget.cpp b/widgets/cddaheaderwidget.cpp index 6091df0..9bcf44d 100644 --- a/widgets/cddaheaderwidget.cpp +++ b/widgets/cddaheaderwidget.cpp @@ -1,896 +1,896 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "cddaheaderwidget.h" #include #include #include static QImage mirrorImage(const QImage &img, MirrorStyle mirrorStyle = MirrorOverX, FadeStyle fadeStyle = FadeDown) { /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This function is part of the Graphics Dojo project on Qt Labs. ** ** This file may be used under the terms of the GNU General Public ** License version 2.0 or 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of ** this file. Please review the following information to ensure GNU ** General Public Licensing requirements will be met: ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and ** http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ QImage tmpImage = img; if (mirrorStyle != NoMirror) tmpImage = tmpImage.mirrored(mirrorStyle == MirrorOverY, mirrorStyle == MirrorOverX); if (fadeStyle != NoFade) { QPoint p1, p2; if (fadeStyle == FadeDown) p2.setY(tmpImage.height()); else if (fadeStyle == FadeUp) p1.setY(tmpImage.height()); else if (fadeStyle == FadeRight) p2.setX(tmpImage.width()); else if (fadeStyle == FadeLeft) p1.setX(tmpImage.width()); QLinearGradient gradient(p1, p2); gradient.setColorAt(0, Qt::white); gradient.setColorAt(0.2, QColor(0, 0, 0, 20)); gradient.setColorAt(1, Qt::transparent); QPainter p(&tmpImage); p.setCompositionMode(QPainter::CompositionMode_DestinationIn); p.fillRect(0, 0, tmpImage.width(), tmpImage.height(), gradient); p.end(); } return tmpImage; } static QImage fadeImage(const QImage &img, float val, const QColor &color) { /* This function is part of the KDE libraries Copyright (C) 1998, 1999, 2001, 2002 Daniel M. Duley (C) 1998, 1999 Christian Tibirna (C) 1998, 1999 Dirk Mueller */ QImage tmpImage = img; if (tmpImage.width() == 0 || tmpImage.height() == 0) return tmpImage; // We don't handle bitmaps if (tmpImage.depth() == 1) return tmpImage; unsigned char tbl[256]; for (int i = 0; i < 256; ++i) tbl[i] = (int)(val * i + 0.5); int red = color.red(); int green = color.green(); int blue = color.blue(); QRgb col; int r, g, b, cr, cg, cb; if (tmpImage.depth() <= 8) { // pseudo color for (int i = 0; i < tmpImage.numColors(); i++) { col = tmpImage.color(i); cr = qRed(col); cg = qGreen(col); cb = qBlue(col); if (cr > red) r = cr - tbl[cr - red]; else r = cr + tbl[red - cr]; if (cg > green) g = cg - tbl[cg - green]; else g = cg + tbl[green - cg]; if (cb > blue) b = cb - tbl[cb - blue]; else b = cb + tbl[blue - cb]; tmpImage.setColor(i, qRgba(r, g, b, qAlpha(col))); } } else { // truecolor for (int y = 0; y < tmpImage.height(); ++y) { QRgb *data = (QRgb *)tmpImage.scanLine(y); for (int x = 0; x < tmpImage.width(); ++x) { col = *data; cr = qRed(col); cg = qGreen(col); cb = qBlue(col); if (cr > red) r = cr - tbl[cr - red]; else r = cr + tbl[red - cr]; if (cg > green) g = cg - tbl[cg - green]; else g = cg + tbl[green - cg]; if (cb > blue) b = cb - tbl[cb - blue]; else b = cb + tbl[blue - cb]; *data++ = qRgba(r, g, b, qAlpha(col)); } } } return tmpImage; } /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** The following five functions are part of the Graphics Dojo project ** on Trolltech Labs. ** ** This file may be used under the terms of the GNU General Public ** License version 2.0 or 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of ** this file. Please review the following information to ensure GNU ** General Public Licensing requirements will be met: ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and ** http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ static inline int sign(int x) { return x < 0 ? -1 : 1; } static inline int blend(int a, int b, int blendA, int blendB) { return blendA * a + blendB * b; } // bilinear blend static inline int blend(unsigned int *s, int blendX, int blendY, int shift) { unsigned int src[] = {(s[0] >> shift) & 0xff, (s[1] >> shift) & 0xff, (s[2] >> shift) & 0xff, (s[3] >> shift) & 0xff}; int da = blend(src[0], src[1], FP_FACTOR - blendX, blendX); int db = blend(src[2], src[3], FP_FACTOR - blendX, blendX); return blend(da, db, FP_FACTOR - blendY, blendY) / (FP_FACTOR * FP_FACTOR); } static void processScanlines(QImage &img, int sy, int ey, int sx, int ex) { int dx = sign(ex - sx); int dy = sign(ey - sy); QRgb *data = (QRgb *)img.bits(); int width = img.width(); int height = img.height(); if (dy == 1 && sy >= height) return; if (dx == 1 && sx >= width) return; if (dy != 1 && sy < 0) return; if (dx != 1 && sx < 0) return; int actual_sy = (dy == 1) ? qMax(0, sy) : qMin(height - 1, sy); int actual_ey = (dy == 1) ? qMin(height, ey) : qMax(-1, ey); int actual_sx = (dx == 1) ? qMax(0, sx) : qMin(width - 1, sx); int actual_ex = (dx == 1) ? qMin(width, ex) : qMax(-1, ex); if (dy == 1 && actual_sy >= actual_ey) return; if (dy != 1 && actual_sy <= actual_ey) return; if (dx == 1 && actual_sx >= actual_ex) return; if (dx != 1 && actual_sx <= actual_ex) return; for (int y = actual_sy; y != actual_ey; y += dy) { QRgb *dst = data + y * width; int srcY = y * FP_FACTOR + (sy - y) * 8; int scanLine = srcY / FP_FACTOR; - QRgb *srcA = scanLine >= 0 && scanLine < height ? data + scanLine * width : 0; + QRgb *srcA = scanLine >= 0 && scanLine < height ? data + scanLine * width : nullptr; ++scanLine; - QRgb *srcB = scanLine >= 0 && scanLine < height ? data + scanLine * width : 0; + QRgb *srcB = scanLine >= 0 && scanLine < height ? data + scanLine * width : nullptr; if (!srcA && !srcB) { for (int x = sx; x != ex; x += dx) dst[x] = 0; continue; } int blendY = srcY % FP_FACTOR; for (int x = actual_sx; x != actual_ex; x += dx) { int srcX = x * FP_FACTOR + (sx - x) * 8; int da = srcX / FP_FACTOR; int db = da + 1; int blendX = srcX % FP_FACTOR; QRgb src[4] = {srcA ? srcA[da] : 0, srcA ? srcA[db] : 0, srcB ? srcB[da] : 0, srcB ? srcB[db] : 0}; int red = blend(src, blendX, blendY, 16); int green = blend(src, blendX, blendY, 8); int blue = blend(src, blendX, blendY, 0); red = blend(red, qRed(dst[x]), FP_FACTOR - 32, 128) / FP_FACTOR; green = blend(green, qGreen(dst[x]), FP_FACTOR - 32, 128) / FP_FACTOR; blue = blend(blue, qBlue(dst[x]), FP_FACTOR - 32, 128) / FP_FACTOR; red = qMin(red, 255); green = qMin(green, 255); blue = qMin(blue, 255); dst[x] = qRgba(red, green, blue, qAlpha(dst[x])); } } } static void radialBlur(QImage &img, int cx, int cy) { int w = img.width(); int h = img.height(); processScanlines(img, cy - 1, -1, cx - 1, -1); processScanlines(img, cy - 1, -1, cx, w); processScanlines(img, cy, h, cx - 1, -1); processScanlines(img, cy, h, cx, w); } CDDAHeaderWidget ::CDDAHeaderWidget(CDDAModel *cddaModel, QWidget *parent, const int coverSize, const int padding) : QWidget(parent) { cdda_model = cddaModel; if (!cdda_model) { qDebug() << "CDDAModel is NULL!"; return; } connect(cdda_model, SIGNAL(modelReset()), this, SLOT(update())); setup_actions(); qDebug() << "coverSize:" << coverSize; this->cover_size = coverSize; this->i_cover_checksum = 1; this->padding = padding; animation_up = false; animation_down = false; scale_up = false; scale_down = false; fade_in = false; fade_out = false; scale_factor = 1.0; opacity_factor = 1.0; setMouseTracking(true); cursor_on_cover = false; cursor_on_link1 = false; cursor_on_link2 = false; connect(this, SIGNAL(coverDown()), this, SLOT(cover_is_down())); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(context_menu(const QPoint &))); - cover_browser_dialog = NULL; + cover_browser_dialog = nullptr; fetching_cover_in_progress = false; setContextMenuPolicy(Qt::CustomContextMenu); timer.setInterval(40); connect(&timer, SIGNAL(timeout()), this, SLOT(trigger_repaint())); setMinimumSize(QSize(cover_size + (padding * 2), (int)(cover_size * 1.4) + (padding * 2))); tmp_dir = new TmpDir("audex", "cover"); update(); } CDDAHeaderWidget::~CDDAHeaderWidget() { delete action_collection; delete tmp_dir; } QSize CDDAHeaderWidget::sizeHint() const { return QSize((cover_size * 1.5) + (padding * 2), (int)(cover_size * 1.4) + (padding * 2)); } void CDDAHeaderWidget::setCover(CachedImage *cover) { if (cover) { i_cover_checksum = cover->checksum(); } else { i_cover_checksum = 0; } if (this->i_cover.isNull()) { if (cover) { this->i_cover = cover->coverImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); } else { QImage image = QImage(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QString("audex/images/nocover.png"))); this->i_cover = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); } animation_up = true; fade_in = true; scale_factor = 0.7; opacity_factor = 0.0; } else { if (cover) { this->i_cover_holding = cover->coverImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); } else { QImage image = QImage(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QString("audex/images/nocover.png"))); this->i_cover_holding = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); } animation_down = true; scale_down = true; scale_factor = 1.0; opacity_factor = 1.0; } timer.start(); } bool CDDAHeaderWidget::isEnabled() const { return enabled; } void CDDAHeaderWidget::setEnabled(bool enabled) { this->enabled = enabled; repaint(); } void CDDAHeaderWidget::googleAuto() { qDebug() << "Google AUTO cover fetch"; if ((cdda_model->empty()) || (fetching_cover_in_progress)) return; QApplication::restoreOverrideCursor(); cursor_on_cover = false; fetching_cover_in_progress = true; action_collection->action("fetch")->setEnabled(false); cover_browser_dialog = new CoverBrowserDialog(this); connect(cover_browser_dialog, SIGNAL(allCoverThumbnailsFetched()), this, SLOT(fetch_first_cover())); connect(cover_browser_dialog, SIGNAL(nothingFetched()), this, SLOT(auto_fetch_cover_failed())); QString artist = cdda_model->artist(); QString title = cdda_model->title(); int lastColonPos = title.lastIndexOf(':'); while (lastColonPos > 0) { title = title.left(lastColonPos); lastColonPos = title.lastIndexOf(':'); } cover_browser_dialog->fetchThumbnails(QString("%1 %2").arg(artist, title), 1); } void CDDAHeaderWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QPainter p; p.begin(this); if (enabled) { bool vertical = rect().height() > rect().width() && rect().width() < ((cover_size + padding) * 2); int xOffset = vertical ? padding : (padding * 2) + cover_size, yOffset = vertical ? (padding * 2) + cover_size + 24 : padding; QImage scaled_cover = i_cover.scaled((int)(scale_factor * cover_size), (int)(scale_factor * cover_size), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); QImage faded_cover = fadeImage(scaled_cover, 1 - opacity_factor, palette().background().color()); p.drawImage((cover_size / 2 - (scaled_cover.width() / 2)) + padding, (cover_size / 2 - (scaled_cover.height() / 2)) + padding, faded_cover); cover_rect = QRect(padding, padding, scaled_cover.width(), scaled_cover.height()); QImage mirror_img = mirrorImage(faded_cover); // we shear it a along the x axis to produce the nice leaning to the side effect. (valid only for MirrorOverX) // mirror_img = mirror_img.transformed(QMatrix().shear(0.2, 0.0), Qt::SmoothTransformation); radialBlur(mirror_img, 50, 50); p.drawImage((cover_size / 2 - (scaled_cover.width() / 2)) + padding, (cover_size / 2 - (scaled_cover.height() / 2)) + padding + mirror_img.height() + 5, mirror_img); p.setBrush(palette().text()); QFont font(QApplication::font()); int pixelSize(font.pixelSize() == -1 ? (font.pointSize() * QX11Info::appDpiX() + 36) / 72 : font.pixelSize()), width = rect().width() - (xOffset + 1); font.setPixelSize((int)((((double)pixelSize) * 1.5) + 0.5)); font.setBold(true); p.setFont(font); yOffset += p.fontMetrics().lineSpacing() * 1.2; p.drawText(xOffset, yOffset, p.fontMetrics().elidedText(cdda_model->artist(), Qt::ElideRight, width)); font.setPixelSize(pixelSize); font.setBold(true); font.setItalic(true); p.setFont(font); yOffset += pixelSize; p.drawText(xOffset, yOffset, p.fontMetrics().elidedText(cdda_model->title(), Qt::ElideRight, width)); yOffset += p.fontMetrics().lineSpacing() * 1.5; font.setBold(false); font.setItalic(false); p.setFont(font); QFontMetrics fm(font); QString yearLabel(i18n("Released: ")), genreLabel(i18n("Genre: ")), cdNoLabel(i18n("CD Number: ")); int maxWidth(fm.width(yearLabel)); if ((width = fm.width(genreLabel)) > maxWidth) maxWidth = width; if (cdda_model->isMultiCD() && (width = fm.width(cdNoLabel))) maxWidth = width; width = rect().width() - (xOffset + 1); if (!cdda_model->year().isEmpty()) { p.drawText(xOffset, yOffset, yearLabel); p.drawText(xOffset + maxWidth, yOffset, fm.elidedText(cdda_model->year(), Qt::ElideRight, width - maxWidth)); yOffset += fm.lineSpacing(); } if (!cdda_model->genre().isEmpty()) { p.drawText(xOffset, yOffset, genreLabel); p.drawText(xOffset + maxWidth, yOffset, fm.elidedText(cdda_model->genre(), Qt::ElideRight, width - maxWidth)); yOffset += fm.lineSpacing(); } if (cdda_model->isMultiCD()) { p.drawText(xOffset, yOffset, cdNoLabel); p.drawText(xOffset + maxWidth, yOffset, QString().setNum(cdda_model->cdNum())); yOffset += fm.lineSpacing(); } font.setUnderline(true); p.setFont(font); // links fm = QFontMetrics(font); QString link1 = i18n("Edit Data"); QString link2 = i18n("Wikipedia"); KColorScheme kcs(QPalette::Active); p.setPen(kcs.foreground(KColorScheme::LinkText).color()); link1_rect = fm.boundingRect(link1); link2_rect = fm.boundingRect(link2); yOffset = vertical ? yOffset + fm.lineSpacing() : (yOffset > (padding + cover_size) ? yOffset : (padding + cover_size)); p.drawText(xOffset, yOffset, link1); p.drawText(xOffset + (link1_rect.height() / 2) + link1_rect.width(), yOffset, link2); link1_rect = QRect(xOffset, yOffset + link1_rect.y(), link1_rect.width(), link1_rect.height()); link2_rect = QRect(xOffset + (link1_rect.height() / 2) + link1_rect.width(), yOffset + link2_rect.y(), link2_rect.width(), link2_rect.height()); } else { // disabled QFont font(QApplication::font()); if (-1 == font.pixelSize()) { font.setPointSizeF(font.pointSizeF() * 1.5); } else { font.setPixelSize(font.pixelSize() * 1.5); } font.setBold(true); font.setItalic(true); p.setFont(font); p.drawText(rect(), Qt::AlignCenter | Qt::AlignVCenter, i18n("No audio CD detected")); } p.end(); } void CDDAHeaderWidget::mouseMoveEvent(QMouseEvent *event) { if (cover_rect.contains(event->pos())) { if (!cursor_on_cover) { QApplication::setOverrideCursor(QCursor(Qt::PointingHandCursor)); cursor_on_cover = true; } } else if (link1_rect.contains(event->pos())) { if (!cursor_on_link1) { QApplication::setOverrideCursor(QCursor(Qt::PointingHandCursor)); cursor_on_link1 = true; } } else if (link2_rect.contains(event->pos())) { if (!cursor_on_link2) { QApplication::setOverrideCursor(QCursor(Qt::PointingHandCursor)); cursor_on_link2 = true; } } else { if (cursor_on_cover) { QApplication::restoreOverrideCursor(); cursor_on_cover = false; } else if (cursor_on_link1) { QApplication::restoreOverrideCursor(); cursor_on_link1 = false; } else if (cursor_on_link2) { QApplication::restoreOverrideCursor(); cursor_on_link2 = false; } } } void CDDAHeaderWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { if ((cursor_on_cover) && (!fetching_cover_in_progress)) { if (cdda_model->isCoverEmpty()) { if (cdda_model->empty()) { load(); } else { google(); } } else { view_cover(); } } if (cursor_on_link1) edit_data(); if (cursor_on_link2) wikipedia(); } } void CDDAHeaderWidget::update() { action_collection->action("fetch")->setEnabled(!cdda_model->empty()); bool activate = false; if (cdda_model->isCoverEmpty()) { if (i_cover_checksum) - setCover(NULL); + setCover(nullptr); } else { qDebug() << "current cover checksum:" << i_cover_checksum; qDebug() << "new cover checksum:" << cdda_model->coverChecksum(); if (i_cover_checksum != cdda_model->coverChecksum()) setCover(cdda_model->cover()); activate = true; } action_collection->action("save")->setEnabled(activate); action_collection->action("view")->setEnabled(activate); action_collection->action("remove")->setEnabled(activate); repaint(); } void CDDAHeaderWidget::trigger_repaint() { if (animation_down) { if (scale_down) { scale_factor -= 0.08; if (qFuzzyCompare(scale_factor, .7) || scale_factor < .7) { scale_down = false; fade_out = true; } } else if (fade_out) { opacity_factor -= 0.16; if (qFuzzyCompare(opacity_factor, 0) || opacity_factor < 0) { opacity_factor = 0; fade_out = false; animation_down = false; timer.stop(); emit coverDown(); } } } else if (animation_up) { if (fade_in) { opacity_factor += 0.16; if (qFuzzyCompare(opacity_factor, 1) || opacity_factor > 1) { opacity_factor = 1; fade_in = false; scale_up = true; } } else if (scale_up) { scale_factor += 0.08; if (qFuzzyCompare(scale_factor, 1) || scale_factor > 1) { scale_up = false; animation_up = false; timer.stop(); emit coverUp(); } } } repaint(); } void CDDAHeaderWidget::cover_is_down() { this->i_cover = i_cover_holding; animation_up = true; fade_in = true; scale_factor = .7; opacity_factor = 0.0; timer.start(); } void CDDAHeaderWidget::google() { qDebug() << "Google cover fetch"; if ((cdda_model->empty()) || (fetching_cover_in_progress)) return; QApplication::restoreOverrideCursor(); cursor_on_cover = false; fetching_cover_in_progress = true; action_collection->action("fetch")->setEnabled(false); cover_browser_dialog = new CoverBrowserDialog(this); connect(cover_browser_dialog, SIGNAL(coverFetched(const QByteArray &)), this, SLOT(set_cover(const QByteArray &))); connect(cover_browser_dialog, SIGNAL(nothingFetched()), this, SLOT(fetch_cover_failed())); QString artist = cdda_model->artist(); QString title = cdda_model->title(); int lastColonPos = title.lastIndexOf(':'); while (lastColonPos > 0) { title = title.left(lastColonPos); lastColonPos = title.lastIndexOf(':'); } cover_browser_dialog->fetchThumbnails(QString("%1 %2").arg(artist, title)); if (cover_browser_dialog->exec() != QDialog::Accepted) { fetching_cover_in_progress = false; delete cover_browser_dialog; - cover_browser_dialog = NULL; + cover_browser_dialog = nullptr; action_collection->action("fetch")->setEnabled(true); } } void CDDAHeaderWidget::load() { qDebug() << "Supported cover image file MIME types:" << cdda_model->coverSupportedMimeTypeList(); QString filename = QFileDialog::getOpenFileName(this, i18n("Load Cover"), QDir::homePath(), cdda_model->coverSupportedMimeTypeList()); if (!filename.isEmpty()) { if (!cdda_model->setCover(filename)) { ErrorDialog::show(this, cdda_model->lastError().message(), cdda_model->lastError().details()); } } } void CDDAHeaderWidget::save() { QString filename = QFileDialog::getSaveFileName(this, i18n("Save Cover"), QDir::homePath() + '/' + cdda_model->title() + ".jpg", cdda_model->coverSupportedMimeTypeList()); if (!filename.isEmpty()) { if (!cdda_model->saveCoverToFile(filename)) { ErrorDialog::show(this, cdda_model->lastError().message(), cdda_model->lastError().details()); } } } void CDDAHeaderWidget::view_cover() { QString tmp_path = tmp_dir->tmpPath(); if (tmp_dir->error()) { QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::TempLocation); tmp_path = dirs.size() ? dirs[0] : "/var/tmp/"; if (tmp_path.right(1) != "/") tmp_path += "/"; qDebug() << "Temporary folder in use:" << tmp_path; } QString filename = tmp_path + QString("%1.jpeg").arg(cdda_model->coverChecksum()); cdda_model->saveCoverToFile(filename); QDesktopServices::openUrl(QUrl(filename)); } void CDDAHeaderWidget::remove() { cdda_model->clearCover(); update(); } void CDDAHeaderWidget::edit_data() { QApplication::restoreOverrideCursor(); cursor_on_link1 = false; CDDAHeaderDataDialog *dialog = new CDDAHeaderDataDialog(cdda_model, this); if (dialog->exec() != QDialog::Accepted) { delete dialog; return; } delete dialog; update(); emit headerDataChanged(); } void CDDAHeaderWidget::wikipedia() { int locale = Preferences::wikipediaLocale(); QString l; if (locale == 0) l = "en"; if (locale == 1) l = "de"; if (locale == 2) l = "fr"; if (locale == 3) l = "pl"; if (locale == 4) l = "ja"; if (locale == 5) l = "it"; if (locale == 6) l = "nl"; if (locale == 7) l = "es"; if (locale == 8) l = "pt"; if (locale == 9) l = "sv"; if (l.isEmpty()) l = "en"; QDesktopServices::openUrl(QUrl(QString("http://%1.wikipedia.org/wiki/").arg(l) + QUrl::toPercentEncoding(cdda_model->artist()))); } void CDDAHeaderWidget::set_cover(const QByteArray &cover) { if (!cover.isEmpty()) cdda_model->setCover(cover); fetching_cover_in_progress = false; action_collection->action("fetch")->setEnabled(true); if (cover_browser_dialog) { delete cover_browser_dialog; - cover_browser_dialog = NULL; + cover_browser_dialog = nullptr; } if (!cover.isEmpty()) update(); } void CDDAHeaderWidget::fetch_first_cover() { if (cover_browser_dialog) { if (cover_browser_dialog->count() == 0) { qDebug() << "no cover found"; ErrorDialog::show(this, i18n("No cover found."), i18n("Check your artist name and title. Otherwise you can load a custom cover from an image file.")); delete cover_browser_dialog; - cover_browser_dialog = NULL; + cover_browser_dialog = nullptr; fetching_cover_in_progress = false; action_collection->action("fetch")->setEnabled(true); } else { connect(cover_browser_dialog, SIGNAL(coverFetched(const QByteArray &)), this, SLOT(set_cover(const QByteArray &))); cover_browser_dialog->startFetchCover(0); } } } void CDDAHeaderWidget::fetchCoverFinished(bool showDialog) { if (cover_browser_dialog) { if (showDialog) { ErrorDialog::show(this, i18n("No cover found."), i18n("Check your artist name and title. Otherwise you can load a custom cover from an image file.")); } delete cover_browser_dialog; - cover_browser_dialog = NULL; + cover_browser_dialog = nullptr; } fetching_cover_in_progress = false; action_collection->action("fetch")->setEnabled(true); } void CDDAHeaderWidget::auto_fetch_cover_failed() { fetchCoverFinished(false); } void CDDAHeaderWidget::fetch_cover_failed() { fetchCoverFinished(true); } void CDDAHeaderWidget::context_menu(const QPoint &point) { qDebug() << "context menu requested at point" << point; if ((cursor_on_cover) && (!fetching_cover_in_progress)) { QApplication::restoreOverrideCursor(); cursor_on_cover = false; QMenu contextMenu(this); QMouseEvent *mevent = new QMouseEvent(QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier); contextMenu.clear(); contextMenu.addAction(action_collection->action("fetch")); contextMenu.addAction(action_collection->action("load")); contextMenu.addAction(action_collection->action("save")); contextMenu.addSeparator(); contextMenu.addAction(action_collection->action("view")); contextMenu.addSeparator(); contextMenu.addAction(action_collection->action("remove")); contextMenu.exec(mevent->globalPos()); } } void CDDAHeaderWidget::setup_actions() { action_collection = new KActionCollection(this); QAction *fetchCoverAction = new QAction(this); fetchCoverAction->setText(i18n("Fetch cover from Google...")); action_collection->addAction("fetch", fetchCoverAction); connect(fetchCoverAction, SIGNAL(triggered(bool)), this, SLOT(google())); QAction *loadCoverAction = new QAction(this); loadCoverAction->setText(i18n("Set Custom Cover...")); action_collection->addAction("load", loadCoverAction); connect(loadCoverAction, SIGNAL(triggered(bool)), this, SLOT(load())); QAction *saveCoverAction = new QAction(this); saveCoverAction->setText(i18n("Save Cover To File...")); action_collection->addAction("save", saveCoverAction); connect(saveCoverAction, SIGNAL(triggered(bool)), this, SLOT(save())); QAction *viewCoverAction = new QAction(this); viewCoverAction->setText(i18n("Show Full Size Cover...")); action_collection->addAction("view", viewCoverAction); connect(viewCoverAction, SIGNAL(triggered(bool)), this, SLOT(view_cover())); QAction *removeCoverAction = new QAction(this); removeCoverAction->setText(i18n("Remove Cover")); action_collection->addAction("remove", removeCoverAction); connect(removeCoverAction, SIGNAL(triggered(bool)), this, SLOT(remove())); } diff --git a/widgets/cddaheaderwidget.h b/widgets/cddaheaderwidget.h index a7c78d2..8c46a37 100644 --- a/widgets/cddaheaderwidget.h +++ b/widgets/cddaheaderwidget.h @@ -1,147 +1,147 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CDDAHEADERWIDGET_H #define CDDAHEADERWIDGET_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "preferences.h" #include "dialogs/cddaheaderdatadialog.h" #include "dialogs/coverbrowserdialog.h" #include "dialogs/errordialog.h" #include "models/cddamodel.h" #include "utils/cachedimage.h" #include "utils/coverfetcher.h" #include "utils/tmpdir.h" // fixed point defines #define FP_BITS 10 #define FP_FACTOR (1 << FP_BITS) enum FadeStyle { NoFade, FadeDown, FadeRight, FadeUp, FadeLeft }; enum MirrorStyle { NoMirror, MirrorOverX, MirrorOverY }; class CDDAHeaderWidget : public QWidget { Q_OBJECT public: - explicit CDDAHeaderWidget(CDDAModel *cddaModel, QWidget *parent = 0, const int coverSize = 128, const int padding = 20); + explicit CDDAHeaderWidget(CDDAModel *cddaModel, QWidget *parent = nullptr, const int coverSize = 128, const int padding = 20); ~CDDAHeaderWidget() override; QSize sizeHint() const override; void setCover(CachedImage *cover); bool isEnabled() const; public slots: void setEnabled(bool enabled); void googleAuto(); signals: void headerDataChanged(); void coverUp(); void coverDown(); protected: void paintEvent(QPaintEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void fetchCoverFinished(bool showDialog); private slots: void update(); void trigger_repaint(); void cover_is_down(); void google(); void load(); void save(); void view_cover(); void remove(); void edit_data(); void wikipedia(); void set_cover(const QByteArray &cover); void fetch_first_cover(); void fetch_cover_failed(); void auto_fetch_cover_failed(); void context_menu(const QPoint &point); private: CDDAModel *cdda_model; KActionCollection *action_collection; int cover_size; int padding; quint16 i_cover_checksum; QImage i_cover; QImage i_cover_holding; QTimer timer; bool animation_up; bool animation_down; qreal scale_factor; bool scale_up; bool scale_down; qreal opacity_factor; bool fade_in; bool fade_out; QRect cover_rect; bool cursor_on_cover; QRect link1_rect; bool cursor_on_link1; QRect link2_rect; bool cursor_on_link2; void setup_actions(); bool enabled; bool fetching_cover_in_progress; CoverBrowserDialog *cover_browser_dialog; TmpDir *tmp_dir; }; #endif diff --git a/widgets/customwidget.h b/widgets/customwidget.h index df7adc6..de14887 100644 --- a/widgets/customwidget.h +++ b/widgets/customwidget.h @@ -1,71 +1,71 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CUSTOMWIDGET_H #define CUSTOMWIDGET_H #include #include #include "utils/encoderassistant.h" #include "utils/error.h" #include "utils/parameters.h" #include "dialogs/commandwizarddialog.h" #include "ui_customwidgetUI.h" class customWidgetUI : public QWidget, public Ui::CustomWidgetUI { public: explicit customWidgetUI(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class customWidget : public customWidgetUI { Q_OBJECT public: - explicit customWidget(Parameters *parameters, QWidget *parent = 0); + explicit customWidget(Parameters *parameters, QWidget *parent = nullptr); ~customWidget() override; Error lastError() const { return error; } inline bool isChanged() const { return changed; } public slots: bool save(); void pattern_wizard(); signals: void triggerChanged(); private slots: void trigger_changed(); private: Parameters *parameters; Error error; bool changed; }; #endif diff --git a/widgets/devicewidget.h b/widgets/devicewidget.h index 98ba6cf..cf6e752 100644 --- a/widgets/devicewidget.h +++ b/widgets/devicewidget.h @@ -1,48 +1,48 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef DEVICEWIDGET_H #define DEVICEWIDGET_H #include #include #include "preferences.h" #include "ui_devicewidgetUI.h" class deviceWidgetUI : public QWidget, public Ui::DeviceWidgetUI { public: explicit deviceWidgetUI(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class deviceWidget : public deviceWidgetUI { Q_OBJECT public: - explicit deviceWidget(QWidget *parent = 0); + explicit deviceWidget(QWidget *parent = nullptr); ~deviceWidget() override; }; #endif diff --git a/widgets/faacwidget.h b/widgets/faacwidget.h index a4175cd..c3ae94e 100644 --- a/widgets/faacwidget.h +++ b/widgets/faacwidget.h @@ -1,70 +1,70 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FAACWIDGET_H #define FAACWIDGET_H #include #include #include "utils/encoderassistant.h" #include "utils/error.h" #include "utils/parameters.h" #include "ui_faacwidgetUI.h" class faacWidgetUI : public QWidget, public Ui::FAACWidgetUI { public: explicit faacWidgetUI(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class faacWidget : public faacWidgetUI { Q_OBJECT public: - explicit faacWidget(Parameters *parameters, QWidget *parent = 0); + explicit faacWidget(Parameters *parameters, QWidget *parent = nullptr); ~faacWidget() override; Error lastError() const { return error; } inline bool isChanged() const { return changed; } public slots: bool save(); signals: void triggerChanged(); private slots: void quality_changed_by_slider(int quality); void quality_changed_by_spinbox(int quality); void trigger_changed(); private: Parameters *parameters; Error error; bool changed; }; #endif diff --git a/widgets/flacwidget.h b/widgets/flacwidget.h index 3823005..faa31d7 100644 --- a/widgets/flacwidget.h +++ b/widgets/flacwidget.h @@ -1,70 +1,70 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef FLACWIDGET_H #define FLACWIDGET_H #include #include #include "utils/encoderassistant.h" #include "utils/error.h" #include "utils/parameters.h" #include "ui_flacwidgetUI.h" class flacWidgetUI : public QWidget, public Ui::FLACWidgetUI { public: explicit flacWidgetUI(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class flacWidget : public flacWidgetUI { Q_OBJECT public: - explicit flacWidget(Parameters *parameters, QWidget *parent = 0); + explicit flacWidget(Parameters *parameters, QWidget *parent = nullptr); ~flacWidget() override; inline Error lastError() const { return error; } inline bool isChanged() const { return changed; } public slots: bool save(); signals: void triggerChanged(); private slots: void compression_changed_by_slider(int compression); void compression_changed_by_spinbox(int compression); void trigger_changed(); private: Parameters *parameters; Error error; bool changed; }; #endif diff --git a/widgets/generalsettingswidget.h b/widgets/generalsettingswidget.h index b830892..fb5eb16 100644 --- a/widgets/generalsettingswidget.h +++ b/widgets/generalsettingswidget.h @@ -1,48 +1,48 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef GENERALSETTINGSWIDGET_H #define GENERALSETTINGSWIDGET_H #include #include #include "preferences.h" #include "ui_generalsettingswidgetUI.h" class generalSettingsWidgetUI : public QWidget, public Ui::GeneralSettingsWidgetUI { public: explicit generalSettingsWidgetUI(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class generalSettingsWidget : public generalSettingsWidgetUI { Q_OBJECT public: - explicit generalSettingsWidget(QWidget *parent = 0); + explicit generalSettingsWidget(QWidget *parent = nullptr); ~generalSettingsWidget() override; }; #endif diff --git a/widgets/lamewidget.h b/widgets/lamewidget.h index 29b74d8..8cb84a3 100644 --- a/widgets/lamewidget.h +++ b/widgets/lamewidget.h @@ -1,80 +1,80 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef LAMEWIDGET_H #define LAMEWIDGET_H #include #include #include "utils/encoderassistant.h" #include "utils/error.h" #include "utils/parameters.h" #include "ui_lamewidgetUI.h" class lameWidgetUI : public QWidget, public Ui::LAMEWidgetUI { public: explicit lameWidgetUI(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class lameWidget : public lameWidgetUI { Q_OBJECT public: - explicit lameWidget(Parameters *parameters, QWidget *parent = 0); + explicit lameWidget(Parameters *parameters, QWidget *parent = nullptr); ~lameWidget() override; inline Error lastError() const { return error; } inline bool isChanged() const { return changed; } signals: void triggerChanged(); public slots: bool save(); private slots: void enable_medium(bool enable); void enable_standard(bool enable); void enable_extreme(bool enable); void enable_insane(bool enable); void enable_custom(bool enable); void enable_CBR(bool enable); void bitrate_changed_by_slider(int bitrate); void bitrate_changed_by_spinbox(int bitrate); void trigger_changed(); private: Parameters *parameters; Error error; bool changed; bool p_cbr_flag; QList bitrates; int real_bitrate; int preset; }; #endif diff --git a/widgets/oggencwidget.h b/widgets/oggencwidget.h index 464dc00..655a732 100644 --- a/widgets/oggencwidget.h +++ b/widgets/oggencwidget.h @@ -1,75 +1,75 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef OGGENCWIDGET_H #define OGGENCWIDGET_H #include #include #include "utils/encoderassistant.h" #include "utils/error.h" #include "utils/parameters.h" #include "ui_oggencwidgetUI.h" class oggencWidgetUI : public QWidget, public Ui::OggEncWidgetUI { public: explicit oggencWidgetUI(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class oggencWidget : public oggencWidgetUI { Q_OBJECT public: - explicit oggencWidget(Parameters *parameters, QWidget *parent = 0); + explicit oggencWidget(Parameters *parameters, QWidget *parent = nullptr); ~oggencWidget() override; inline Error lastError() const { return error; } inline bool isChanged() const { return changed; } public slots: bool save(); signals: void triggerChanged(); private slots: void quality_changed_by_slider(int quality); void quality_changed_by_spinbox(double quality); void set_bitrate(float quality); void enable_min_bitrate(bool enable); void set_minbitrate(int bitrate); void enable_max_bitrate(bool enable); void set_maxbitrate(int bitrate); void trigger_changed(); private: Parameters *parameters; Error error; bool changed; }; #endif diff --git a/widgets/profilewidget.h b/widgets/profilewidget.h index 6a883fd..791c25d 100644 --- a/widgets/profilewidget.h +++ b/widgets/profilewidget.h @@ -1,63 +1,63 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROFILEWIDGET_H #define PROFILEWIDGET_H #include #include #include #include "dialogs/profiledatadialog.h" #include "models/profilemodel.h" #include "ui_profilewidgetUI.h" class profileWidgetUI : public QWidget, public Ui::ProfileWidgetUI { public: explicit profileWidgetUI(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class profileWidget : public profileWidgetUI { Q_OBJECT public: - explicit profileWidget(ProfileModel *profileModel, QWidget *parent = 0); + explicit profileWidget(ProfileModel *profileModel, QWidget *parent = nullptr); ~profileWidget() override; private slots: void _update(); void add_profile(); void rem_profile(); void mod_profile(const QModelIndex &index); void mod_profile(); void copy_profile(); void save_profiles(); void load_profiles(); void init_profiles(); private: ProfileModel *profile_model; }; #endif diff --git a/widgets/remoteserversettingswidget.h b/widgets/remoteserversettingswidget.h index e9b694a..23b516a 100644 --- a/widgets/remoteserversettingswidget.h +++ b/widgets/remoteserversettingswidget.h @@ -1,47 +1,47 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef REMOTESERVERSETTINGSWIDGET_H #define REMOTESERVERSETTINGSWIDGET_H #include #include #include "ui_remoteserversettingswidgetUI.h" class remoteServerSettingsWidgetUI : public QWidget, public Ui::RemoteServerSettingsWidgetUI { public: explicit remoteServerSettingsWidgetUI(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class remoteServerSettingsWidget : public remoteServerSettingsWidgetUI { Q_OBJECT public: - explicit remoteServerSettingsWidget(QWidget *parent = 0); + explicit remoteServerSettingsWidget(QWidget *parent = nullptr); ~remoteServerSettingsWidget() override; private slots: void toggle_upload(bool enabled); }; #endif diff --git a/widgets/wavewidget.h b/widgets/wavewidget.h index ec8001f..7ab1bac 100644 --- a/widgets/wavewidget.h +++ b/widgets/wavewidget.h @@ -1,68 +1,68 @@ /* AUDEX CDDA EXTRACTOR * Copyright (C) 2007-2015 Marco Nelles (audex@maniatek.com) * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef WAVEWIDGET_H #define WAVEWIDGET_H #include #include #include "utils/encoderassistant.h" #include "utils/error.h" #include "utils/parameters.h" #include "ui_wavewidgetUI.h" class waveWidgetUI : public QWidget, public Ui::WAVEWidgetUI { public: explicit waveWidgetUI(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class waveWidget : public waveWidgetUI { Q_OBJECT public: - explicit waveWidget(Parameters *parameters, QWidget *parent = 0); + explicit waveWidget(Parameters *parameters, QWidget *parent = nullptr); ~waveWidget() override; Error lastError() const { return error; } inline bool isChanged() const { return changed; } public slots: bool save(); signals: void triggerChanged(); private slots: void trigger_changed(); private: Parameters *parameters; Error error; bool changed; }; #endif