X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=clip_list.cpp;h=09fe0348e3ff8dc81e7d8e301b7e00979c62743f;hb=087c11c20709f074ae278d8d3d5f00609776f40b;hp=48d8e7bee1c2fbea127957ac3c0709bc7e0ed578;hpb=d23244e5582e7cbb453e23e0d4b5b1faa7605e87;p=nageru diff --git a/clip_list.cpp b/clip_list.cpp index 48d8e7b..09fe034 100644 --- a/clip_list.cpp +++ b/clip_list.cpp @@ -1,44 +1,162 @@ #include "mainwindow.h" -#include "clip_list.h" -#include "ui_mainwindow.h" - +#include #include #include +#include "clip_list.h" +#include "ui_mainwindow.h" + using namespace std; +string pts_to_string(int64_t pts) +{ + // FIXME: This depends on a fixed timebase. + int64_t t = lrint((pts / 12800.0) * 1e3); // In milliseconds. + int ms = t % 1000; + t /= 1000; + int sec = t % 60; + t /= 60; + int min = t % 60; + t /= 60; + int hour = t; + + char buf[256]; + snprintf(buf, sizeof(buf), "%d:%02d:%02d.%03d", hour, min, sec, ms); + return buf; +} + +string duration_to_string(int64_t pts_diff) +{ + // FIXME: This depends on a fixed timebase. + int64_t t = lrint((pts_diff / 12800.0) * 1e3); // In milliseconds. + int ms = t % 1000; + t /= 1000; + int sec = t % 60; + t /= 60; + int min = t; + + char buf[256]; + snprintf(buf, sizeof(buf), "%d:%02d.%03d", min, sec, ms); + return buf; +} + int ClipList::rowCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; 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; - return 7; + 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 { if (!parent.isValid()) return QVariant(); - if (role != Qt::DisplayRole) + 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::IN: + case Column::OUT: + case Column::DURATION: + return Qt::AlignRight + Qt::AlignVCenter; + default: + return Qt::AlignLeft + Qt::AlignVCenter; + } + } + + if (role != Qt::DisplayRole && role != Qt::EditRole) + return QVariant(); + + 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(); + } + case Column::CAMERA_1: + case Column::CAMERA_2: + case Column::CAMERA_3: + case Column::CAMERA_4: { + unsigned stream_idx = column - int(Column::CAMERA_1); + return QString::fromStdString(clips[row].descriptions[stream_idx]); + } + 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(); - switch (column) { - case 0: - return qlonglong(clips[row].pts_in); - case 1: + 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 Qt::AlignLeft + Qt::AlignVCenter; + } + } + + if (role != Qt::DisplayRole && role != Qt::EditRole) + 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 qlonglong(clips[row].pts_out); + 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); + case Column::DESCRIPTION: + return QString::fromStdString(clips[row].descriptions[clips[row].stream_idx]); default: - return QVariant(); + return ""; } } @@ -48,32 +166,204 @@ QVariant ClipList::headerData(int section, Qt::Orientation orientation, int role if (orientation != Qt::Horizontal) return QVariant(); - switch (section) { - case 0: + switch (Column(section)) { + case Column::IN: return "In"; - case 1: + case Column::OUT: return "Out"; - case 2: + case Column::DURATION: return "Duration"; - case 3: + case Column::CAMERA_1: return "Camera 1"; - case 4: + case Column::CAMERA_2: return "Camera 2"; - case 5: + case Column::CAMERA_3: return "Camera 3"; - case 6: + case Column::CAMERA_4: return "Camera 4"; default: return ""; } } -void ClipList::add_clip(int64_t pts_in) +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 ""; + } +} + +Qt::ItemFlags ClipList::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + const int row = index.row(), column = index.column(); + if (size_t(row) >= clips.size()) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + + switch (Column(column)) { + case Column::CAMERA_1: + case Column::CAMERA_2: + case Column::CAMERA_3: + case Column::CAMERA_4: + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled; + default: + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } +} + +Qt::ItemFlags PlayList::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + const int row = index.row(), column = index.column(); + if (size_t(row) >= clips.size()) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + + switch (Column(column)) { + case Column::DESCRIPTION: + case Column::CAMERA: + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; + default: + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } +} + +bool ClipList::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid() || role != Qt::EditRole) { + return false; + } + + const int row = index.row(), column = index.column(); + if (size_t(row) >= clips.size()) + return false; + + switch (Column(column)) { + case Column::CAMERA_1: + case Column::CAMERA_2: + case Column::CAMERA_3: + case Column::CAMERA_4: { + unsigned stream_idx = column - int(Column::CAMERA_1); + clips[row].descriptions[stream_idx] = value.toString().toStdString(); + emit_data_changed(row); + return true; + } + default: + return false; + } +} + +bool PlayList::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid() || role != Qt::EditRole) { + return false; + } + + const int row = index.row(), column = index.column(); + if (size_t(row) >= clips.size()) + return false; + + switch (Column(column)) { + case Column::DESCRIPTION: + clips[row].descriptions[clips[row].stream_idx] = value.toString().toStdString(); + emit_data_changed(row); + return true; + case Column::CAMERA: { + bool ok; + int camera_idx = value.toInt(&ok); + if (!ok || camera_idx < 1 || camera_idx > NUM_CAMERAS) { + return false; + } + clips[row].stream_idx = camera_idx - 1; + emit_data_changed(row); + return true; + } + default: + return false; + } +} + +void ClipList::add_clip(const Clip &clip) { - Clip clip; - clip.pts_in = pts_in; + beginInsertRows(QModelIndex(), clips.size(), clips.size()); + clips.push_back(clip); + endInsertRows(); +} +void PlayList::add_clip(const Clip &clip) +{ beginInsertRows(QModelIndex(), clips.size(), clips.size()); clips.push_back(clip); endInsertRows(); } + +void PlayList::duplicate_clips(size_t first, size_t last) +{ + beginInsertRows(QModelIndex(), first, last); + clips.insert(clips.begin() + first, clips.begin() + first, clips.begin() + last + 1); + endInsertRows(); +} + +void PlayList::erase_clips(size_t first, size_t last) +{ + beginRemoveRows(QModelIndex(), first, last); + clips.erase(clips.begin() + first, clips.begin() + last + 1); + endRemoveRows(); +} + +void PlayList::move_clips(size_t first, size_t last, int delta) +{ + if (delta == -1) { + beginMoveRows(QModelIndex(), first, last, QModelIndex(), first - 1); + rotate(clips.begin() + first - 1, clips.begin() + first, clips.begin() + last + 1); + } else { + beginMoveRows(QModelIndex(), first, last, QModelIndex(), first + (last-first+1) + 1); + first = clips.size() - first - 1; + last = clips.size() - last - 1; + rotate(clips.rbegin() + last - 1, clips.rbegin() + last, clips.rbegin() + first + 1); + } + endMoveRows(); +} + +void ClipList::emit_data_changed(size_t row) +{ + 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 PlayList::set_currently_playing(int index) +{ + int old_index = currently_playing_index; + if (index != old_index) { + currently_playing_index = index; + if (old_index != -1) { + emit_data_changed(old_index); + } + if (index != -1) { + emit_data_changed(index); + } + } +}