From 93d9a81bcc73658f361d57cc67f0ffa32458534f Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 16 Jun 2018 20:38:17 +0200 Subject: [PATCH] Split ClipList and PlayList. --- clip_list.cpp | 244 +++++++++++++++++++++++++++---------------------- clip_list.h | 89 +++++++++++------- mainwindow.cpp | 19 ++-- 3 files changed, 204 insertions(+), 148 deletions(-) diff --git a/clip_list.cpp b/clip_list.cpp index 62434a6..39dbe9b 100644 --- a/clip_list.cpp +++ b/clip_list.cpp @@ -46,13 +46,19 @@ int ClipList::rowCount(const QModelIndex &parent) const { return clips.size(); } +int PlayList::rowCount(const QModelIndex &parent) const { + if (parent.isValid()) return 0; + return clips.size(); +} + int ClipList::columnCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; - if (display_type == ListDisplay::CLIP_LIST) { - return int(ClipListColumn::NUM_COLUMNS); - } else { - return int(PlayListColumn::NUM_COLUMNS); - } + return int(Column::NUM_COLUMNS); +} + +int PlayList::columnCount(const QModelIndex &parent) const { + if (parent.isValid()) return 0; + return int(Column::NUM_COLUMNS); } QVariant ClipList::data(const QModelIndex &parent, int role) const { @@ -63,77 +69,86 @@ QVariant ClipList::data(const QModelIndex &parent, int role) const { return QVariant(); if (role == Qt::TextAlignmentRole) { - if (display_type == ListDisplay::CLIP_LIST) { - switch (ClipListColumn(column)) { - case ClipListColumn::IN: - case ClipListColumn::OUT: - case ClipListColumn::DURATION: - return Qt::AlignRight + Qt::AlignVCenter; - default: - return Qt::AlignLeft + Qt::AlignVCenter; - } - } else { - switch (PlayListColumn(column)) { - case PlayListColumn::PLAYING: - return Qt::AlignCenter; - case PlayListColumn::IN: - case PlayListColumn::OUT: - case PlayListColumn::DURATION: - return Qt::AlignRight + Qt::AlignVCenter; - case PlayListColumn::CAMERA: - return Qt::AlignCenter; - default: - return Qt::AlignLeft + Qt::AlignVCenter; - } + switch (Column(column)) { + case Column::IN: + case Column::OUT: + case Column::DURATION: + return Qt::AlignRight + Qt::AlignVCenter; + default: + return Qt::AlignLeft + Qt::AlignVCenter; } } if (role != Qt::DisplayRole) return QVariant(); - if (display_type == ListDisplay::CLIP_LIST) { - switch (ClipListColumn(column)) { - case ClipListColumn::IN: - return QString::fromStdString(pts_to_string(clips[row].pts_in)); - case ClipListColumn::OUT: - if (clips[row].pts_out >= 0) { - return QString::fromStdString(pts_to_string(clips[row].pts_out)); - } else { - return QVariant(); - } - case ClipListColumn::DURATION: - if (clips[row].pts_out >= 0) { - return QString::fromStdString(duration_to_string(clips[row].pts_out - clips[row].pts_in)); - } else { - return QVariant(); - } - default: - return ""; + switch (Column(column)) { + case Column::IN: + return QString::fromStdString(pts_to_string(clips[row].pts_in)); + case Column::OUT: + if (clips[row].pts_out >= 0) { + return QString::fromStdString(pts_to_string(clips[row].pts_out)); + } else { + return QVariant(); + } + case Column::DURATION: + if (clips[row].pts_out >= 0) { + return QString::fromStdString(duration_to_string(clips[row].pts_out - clips[row].pts_in)); + } else { + return QVariant(); } - } else { - switch (PlayListColumn(column)) { - case PlayListColumn::PLAYING: - return (row == currently_playing_index) ? "→" : ""; - case PlayListColumn::IN: - return QString::fromStdString(pts_to_string(clips[row].pts_in)); - case PlayListColumn::OUT: - if (clips[row].pts_out >= 0) { - return QString::fromStdString(pts_to_string(clips[row].pts_out)); - } else { - return QVariant(); - } - case PlayListColumn::DURATION: - if (clips[row].pts_out >= 0) { - return QString::fromStdString(duration_to_string(clips[row].pts_out - clips[row].pts_in)); - } else { - return QVariant(); - } - case PlayListColumn::CAMERA: - return qlonglong(clips[row].stream_idx + 1); + default: + return ""; + } +} + +QVariant PlayList::data(const QModelIndex &parent, int role) const { + if (!parent.isValid()) + return QVariant(); + const int row = parent.row(), column = parent.column(); + if (size_t(row) >= clips.size()) + return QVariant(); + + if (role == Qt::TextAlignmentRole) { + switch (Column(column)) { + case Column::PLAYING: + return Qt::AlignCenter; + case Column::IN: + case Column::OUT: + case Column::DURATION: + return Qt::AlignRight + Qt::AlignVCenter; + case Column::CAMERA: + return Qt::AlignCenter; default: - return ""; + return Qt::AlignLeft + Qt::AlignVCenter; } } + + if (role != Qt::DisplayRole) + return QVariant(); + + switch (Column(column)) { + case Column::PLAYING: + return (row == currently_playing_index) ? "→" : ""; + case Column::IN: + return QString::fromStdString(pts_to_string(clips[row].pts_in)); + case Column::OUT: + if (clips[row].pts_out >= 0) { + return QString::fromStdString(pts_to_string(clips[row].pts_out)); + } else { + return QVariant(); + } + case Column::DURATION: + if (clips[row].pts_out >= 0) { + return QString::fromStdString(duration_to_string(clips[row].pts_out - clips[row].pts_in)); + } else { + return QVariant(); + } + case Column::CAMERA: + return qlonglong(clips[row].stream_idx + 1); + default: + return ""; + } } QVariant ClipList::headerData(int section, Qt::Orientation orientation, int role) const { @@ -142,42 +157,47 @@ QVariant ClipList::headerData(int section, Qt::Orientation orientation, int role if (orientation != Qt::Horizontal) return QVariant(); - if (display_type == ListDisplay::CLIP_LIST) { - switch (ClipListColumn(section)) { - case ClipListColumn::IN: - return "In"; - case ClipListColumn::OUT: - return "Out"; - case ClipListColumn::DURATION: - return "Duration"; - case ClipListColumn::CAMERA_1: - return "Camera 1"; - case ClipListColumn::CAMERA_2: - return "Camera 2"; - case ClipListColumn::CAMERA_3: - return "Camera 3"; - case ClipListColumn::CAMERA_4: - return "Camera 4"; - default: - return ""; - } - } else { - switch (PlayListColumn(section)) { - case PlayListColumn::PLAYING: - return ""; - case PlayListColumn::IN: - return "In"; - case PlayListColumn::OUT: - return "Out"; - case PlayListColumn::DURATION: - return "Duration"; - case PlayListColumn::CAMERA: - return "Camera"; - case PlayListColumn::DESCRIPTION: - return "Description"; - default: - return ""; - } + switch (Column(section)) { + case Column::IN: + return "In"; + case Column::OUT: + return "Out"; + case Column::DURATION: + return "Duration"; + case Column::CAMERA_1: + return "Camera 1"; + case Column::CAMERA_2: + return "Camera 2"; + case Column::CAMERA_3: + return "Camera 3"; + case Column::CAMERA_4: + return "Camera 4"; + default: + return ""; + } +} + +QVariant PlayList::headerData(int section, Qt::Orientation orientation, int role) const { + if (role != Qt::DisplayRole) + return QVariant(); + if (orientation != Qt::Horizontal) + return QVariant(); + + switch (Column(section)) { + case Column::PLAYING: + return ""; + case Column::IN: + return "In"; + case Column::OUT: + return "Out"; + case Column::DURATION: + return "Duration"; + case Column::CAMERA: + return "Camera"; + case Column::DESCRIPTION: + return "Description"; + default: + return ""; } } @@ -188,16 +208,24 @@ void ClipList::add_clip(const Clip &clip) endInsertRows(); } +void PlayList::add_clip(const Clip &clip) +{ + beginInsertRows(QModelIndex(), clips.size(), clips.size()); + clips.push_back(clip); + endInsertRows(); +} + void ClipList::emit_data_changed(size_t row) { - if (display_type == ListDisplay::CLIP_LIST) { - emit dataChanged(index(row, 0), index(row, int(ClipListColumn::NUM_COLUMNS))); - } else { - emit dataChanged(index(row, 0), index(row, int(PlayListColumn::NUM_COLUMNS))); - } + emit dataChanged(index(row, 0), index(row, int(Column::NUM_COLUMNS))); +} + +void PlayList::emit_data_changed(size_t row) +{ + emit dataChanged(index(row, 0), index(row, int(Column::NUM_COLUMNS))); } -void ClipList::set_currently_playing(int index) +void PlayList::set_currently_playing(int index) { int old_index = currently_playing_index; if (index != old_index) { diff --git a/clip_list.h b/clip_list.h index 9ca6e63..e97f04f 100644 --- a/clip_list.h +++ b/clip_list.h @@ -14,18 +14,37 @@ struct Clip { unsigned stream_idx = 0; // For the playlist only. }; -// FIXME: This should be split into a separate clip list and play list model. -class ClipList : public QAbstractTableModel { +class DataChangedReceiver { +public: + virtual void emit_data_changed(size_t row) = 0; +}; + +// Like a smart pointer to a Clip, but emits dataChanged when it goes out of scope. +struct ClipProxy { +public: + ClipProxy(Clip &clip, DataChangedReceiver *clip_list, size_t row) + : clip(clip), clip_list(clip_list), row(row) {} + ~ClipProxy() { + if (clip_list != nullptr) { + clip_list->emit_data_changed(row); + } + } + Clip *operator->() { return &clip; } + Clip &operator*() { return clip; } + +private: + Clip &clip; + DataChangedReceiver *clip_list; + size_t row; +}; + +class ClipList : public QAbstractTableModel, public DataChangedReceiver { Q_OBJECT public: - enum class ListDisplay { - CLIP_LIST, - PLAY_LIST - }; - ClipList(ListDisplay display_type) : display_type(display_type) {} + ClipList() {} - enum class ClipListColumn { + enum class Column { IN, OUT, DURATION, @@ -35,7 +54,35 @@ public: CAMERA_4, NUM_COLUMNS }; - enum class PlayListColumn { + + int rowCount(const QModelIndex &parent) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &parent, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + + void add_clip(const Clip &clip); + size_t size() const { return clips.size(); } + bool empty() const { return clips.empty(); } + + ClipProxy clip(size_t index) { return ClipProxy(clips[index], this, index); } + const Clip *clip(size_t index) const { return &clips[index]; } + + ClipProxy back() { return clip(size() - 1); } + const Clip *back() const { return clip(size() - 1); } + + void emit_data_changed(size_t row) override; + +private: + std::vector clips; +}; + +class PlayList : public QAbstractTableModel, public DataChangedReceiver { + Q_OBJECT + +public: + PlayList() {} + + enum class Column { PLAYING, IN, OUT, @@ -54,39 +101,19 @@ public: size_t size() const { return clips.size(); } bool empty() const { return clips.empty(); } - // Like a smart pointer to a Clip, but emits dataChanged when it goes out of scope. - struct ClipProxy { - public: - ClipProxy(Clip &clip, ClipList *clip_list, size_t row) - : clip(clip), clip_list(clip_list), row(row) {} - ~ClipProxy() { - if (clip_list != nullptr) { - clip_list->emit_data_changed(row); - } - } - Clip *operator->() { return &clip; } - Clip &operator*() { return clip; } - - private: - Clip &clip; - ClipList *clip_list; - size_t row; - }; - ClipProxy clip(size_t index) { return ClipProxy(clips[index], this, index); } const Clip *clip(size_t index) const { return &clips[index]; } ClipProxy back() { return clip(size() - 1); } const Clip *back() const { return clip(size() - 1); } - void set_currently_playing(int index); // -1 = none. Only makes sense for the playlist. + void set_currently_playing(int index); // -1 = none. int get_currently_playing() const { return currently_playing_index; } - void emit_data_changed(size_t row); + void emit_data_changed(size_t row) override; private: std::vector clips; - ListDisplay display_type; int currently_playing_index = -1; }; diff --git a/mainwindow.cpp b/mainwindow.cpp index 0b32e3d..ddb08d5 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -14,7 +14,8 @@ using namespace std; MainWindow *global_mainwindow = nullptr; extern int64_t current_pts; -ClipList *cliplist_clips, *playlist_clips; +ClipList *cliplist_clips; +PlayList *playlist_clips; MainWindow::MainWindow() : ui(new Ui::MainWindow) @@ -22,10 +23,10 @@ MainWindow::MainWindow() global_mainwindow = this; ui->setupUi(this); - cliplist_clips = new ClipList(ClipList::ListDisplay::CLIP_LIST); + cliplist_clips = new ClipList(); ui->clip_list->setModel(cliplist_clips); - playlist_clips = new ClipList(ClipList::ListDisplay::PLAY_LIST); + playlist_clips = new PlayList(); ui->playlist->setModel(playlist_clips); // TODO: These are too big for lambdas. @@ -82,10 +83,10 @@ void MainWindow::queue_clicked() } QModelIndex index = selected->currentIndex(); - if (index.column() >= int(ClipList::ClipListColumn::CAMERA_1) && - index.column() <= int(ClipList::ClipListColumn::CAMERA_4)) { + if (index.column() >= int(ClipList::Column::CAMERA_1) && + index.column() <= int(ClipList::Column::CAMERA_4)) { Clip clip = *cliplist_clips->clip(index.row()); - clip.stream_idx = index.column() - int(ClipList::ClipListColumn::CAMERA_1); + clip.stream_idx = index.column() - int(ClipList::Column::CAMERA_1); playlist_clips->add_clip(clip); } } @@ -101,9 +102,9 @@ void MainWindow::preview_clicked() } QModelIndex index = selected->currentIndex(); - if (index.column() >= int(ClipList::ClipListColumn::CAMERA_1) && - index.column() <= int(ClipList::ClipListColumn::CAMERA_4)) { - unsigned stream_idx = index.column() - int(ClipList::ClipListColumn::CAMERA_1); + if (index.column() >= int(ClipList::Column::CAMERA_1) && + index.column() <= int(ClipList::Column::CAMERA_4)) { + unsigned stream_idx = index.column() - int(ClipList::Column::CAMERA_1); preview_player->play_clip(*cliplist_clips->clip(index.row()), stream_idx); } } -- 2.39.2