]> git.sesse.net Git - nageru/commitdiff
Make the UI programmatically dependent on NUM_CAMERAS.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 16 Dec 2018 21:33:18 +0000 (22:33 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 16 Dec 2018 21:33:18 +0000 (22:33 +0100)
futatabi/clip_list.cpp
futatabi/clip_list.h
futatabi/main.cpp
futatabi/mainwindow.cpp
futatabi/mainwindow.h
futatabi/mainwindow.ui

index 9ccbb71367be6a8a4376822262fc7197dbcc2706..0321727cef00888b4ce96bc719b5ed016d6da897 100644 (file)
@@ -58,7 +58,7 @@ int ClipList::columnCount(const QModelIndex &parent) const
 {
        if (parent.isValid())
                return 0;
-       return int(Column::NUM_COLUMNS);
+       return int(Column::NUM_NON_CAMERA_COLUMNS) + NUM_CAMERAS;
 }
 
 int PlayList::columnCount(const QModelIndex &parent) const
@@ -105,15 +105,13 @@ QVariant ClipList::data(const QModelIndex &parent, int role) const
                } 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 "";
+               if (is_camera_column(column)) {
+                       unsigned stream_idx = column - int(Column::CAMERA_1);
+                       return QString::fromStdString(clips[row].descriptions[stream_idx]);
+               } else {
+                       return "";
+               }
        }
 }
 
@@ -213,16 +211,12 @@ QVariant ClipList::headerData(int section, Qt::Orientation orientation, int role
                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 "";
+               if (section >= int(Column::CAMERA_1) && section < int(Column::CAMERA_1) + NUM_CAMERAS) {
+                       return QString::fromStdString("Camera " + to_string(section - int(Column::CAMERA_1) + 1));
+               } else {
+                       return "";
+               }
        }
 }
 
@@ -261,13 +255,9 @@ Qt::ItemFlags ClipList::flags(const QModelIndex &index) const
        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:
+       if (is_camera_column(column)) {
                return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
-       default:
+       } else {
                return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
        }
 }
@@ -301,17 +291,12 @@ bool ClipList::setData(const QModelIndex &index, const QVariant &value, int role
        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: {
+       if (is_camera_column(column)) {
                unsigned stream_idx = column - int(Column::CAMERA_1);
                clips[row].descriptions[stream_idx] = value.toString().toStdString();
                emit_data_changed(row);
                return true;
-       }
-       default:
+       } else {
                return false;
        }
 }
@@ -405,7 +390,7 @@ void PlayList::move_clips(size_t first, size_t last, int delta)
 
 void ClipList::emit_data_changed(size_t row)
 {
-       emit dataChanged(index(row, 0), index(row, int(Column::NUM_COLUMNS)));
+       emit dataChanged(index(row, 0), index(row, int(Column::NUM_NON_CAMERA_COLUMNS) + NUM_CAMERAS));
        emit any_content_changed();
 }
 
index 8dead831106e74783704ad5fab8ea6b9eb9eb675..d2c7f83cd66795b3a2172a4b4c79e01f7826cd1d 100644 (file)
@@ -53,11 +53,8 @@ public:
                IN,
                OUT,
                DURATION,
-               CAMERA_1,
-               CAMERA_2,
-               CAMERA_3,
-               CAMERA_4,
-               NUM_COLUMNS
+               CAMERA_1,  // Then CAMERA_2, CAMERA_3, etc. as needed.
+               NUM_NON_CAMERA_COLUMNS = CAMERA_1
        };
 
        int rowCount(const QModelIndex &parent) const override;
@@ -81,6 +78,11 @@ public:
 
        void emit_data_changed(size_t row) override;
 
+       static bool is_camera_column(int column)
+       {
+               return (column >= int(Column::CAMERA_1) && column < int(Column::CAMERA_1) + NUM_CAMERAS);
+       }
+
 signals:
        void any_content_changed();
 
index 7076230c7429f7cc2c236de332d4a1db253ebbbc..7343df189a3d86aa41ee357c9841aa60d723dab2 100644 (file)
@@ -487,15 +487,7 @@ int record_thread_func()
                        FrameOnDisk frame = write_frame(pkt.stream_index, pts, pkt.data, pkt.size, &db);
 
                        post_to_main_thread([pkt, frame] {
-                               if (pkt.stream_index == 0) {
-                                       global_mainwindow->ui->input1_display->setFrame(pkt.stream_index, frame);
-                               } else if (pkt.stream_index == 1) {
-                                       global_mainwindow->ui->input2_display->setFrame(pkt.stream_index, frame);
-                               } else if (pkt.stream_index == 2) {
-                                       global_mainwindow->ui->input3_display->setFrame(pkt.stream_index, frame);
-                               } else if (pkt.stream_index == 3) {
-                                       global_mainwindow->ui->input4_display->setFrame(pkt.stream_index, frame);
-                               }
+                               global_mainwindow->display_frame(pkt.stream_index, frame);
                        });
 
                        if (last_pts != -1 && global_flags.slow_down_input) {
index 0c12b5c17637c6ce648b7a24841cd09f92e29f9a..8d52c06d022bfdf78349ebc29b056b609b001f13 100644 (file)
@@ -138,30 +138,6 @@ MainWindow::MainWindow()
        connect(ui->stop_btn, &QPushButton::clicked, this, &MainWindow::stop_clicked);
        ui->stop_btn->setEnabled(false);
 
-       QShortcut *preview_1 = new QShortcut(QKeySequence(Qt::Key_1), this);
-       connect(preview_1, &QShortcut::activated, ui->preview_1_btn, &QPushButton::click);
-       connect(ui->input1_display, &JPEGFrameView::clicked, ui->preview_1_btn, &QPushButton::click);
-       connect(ui->preview_1_btn, &QPushButton::clicked, [this]{ preview_angle_clicked(0); });
-       ui->input1_display->set_overlay("1");
-
-       QShortcut *preview_2 = new QShortcut(QKeySequence(Qt::Key_2), this);
-       connect(preview_2, &QShortcut::activated, ui->preview_2_btn, &QPushButton::click);
-       connect(ui->input2_display, &JPEGFrameView::clicked, ui->preview_2_btn, &QPushButton::click);
-       connect(ui->preview_2_btn, &QPushButton::clicked, [this]{ preview_angle_clicked(1); });
-       ui->input2_display->set_overlay("2");
-
-       QShortcut *preview_3 = new QShortcut(QKeySequence(Qt::Key_3), this);
-       connect(preview_3, &QShortcut::activated, ui->preview_3_btn, &QPushButton::click);
-       connect(ui->input3_display, &JPEGFrameView::clicked, ui->preview_3_btn, &QPushButton::click);
-       connect(ui->preview_3_btn, &QPushButton::clicked, [this]{ preview_angle_clicked(2); });
-       ui->input3_display->set_overlay("3");
-
-       QShortcut *preview_4 = new QShortcut(QKeySequence(Qt::Key_4), this);
-       connect(preview_4, &QShortcut::activated, ui->preview_4_btn, &QPushButton::click);
-       connect(ui->input4_display, &JPEGFrameView::clicked, ui->preview_4_btn, &QPushButton::click);
-       connect(ui->preview_4_btn, &QPushButton::clicked, [this]{ preview_angle_clicked(3); });
-       ui->input4_display->set_overlay("4");
-
        connect(ui->playlist_duplicate_btn, &QPushButton::clicked, this, &MainWindow::playlist_duplicate);
 
        connect(ui->playlist_remove_btn, &QPushButton::clicked, this, &MainWindow::playlist_remove);
@@ -202,6 +178,38 @@ MainWindow::MainWindow()
 
        connect(ui->clip_list->selectionModel(), &QItemSelectionModel::currentChanged,
                this, &MainWindow::clip_list_selection_changed);
+
+       // Make the display rows.
+       unsigned display_rows = (NUM_CAMERAS + 1) / 2;
+       ui->video_displays->setStretch(1, display_rows);
+       for (unsigned i = 0; i < NUM_CAMERAS; ++i) {
+               QFrame *frame = new QFrame(this);
+               frame->setAutoFillBackground(true);
+
+               QLayout *layout = new QGridLayout(frame);
+               frame->setLayout(layout);
+               layout->setContentsMargins(3, 3, 3, 3);
+
+               JPEGFrameView *display = new JPEGFrameView(frame);
+               display->setAutoFillBackground(true);
+               layout->addWidget(display);
+
+               ui->input_displays->addWidget(frame, i / 2, i % 2);
+               display->set_overlay(to_string(i + 1));
+
+               QPushButton *preview_btn = new QPushButton(this);
+               preview_btn->setMaximumSize(20, 17);
+               preview_btn->setText(QString::fromStdString(to_string(i + 1)));
+               ui->preview_layout->addWidget(preview_btn);
+
+               displays.emplace_back(FrameAndDisplay{ frame, display, preview_btn });
+
+               connect(display, &JPEGFrameView::clicked, preview_btn, &QPushButton::click);
+               QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_1 + i), this);
+               connect(shortcut, &QShortcut::activated, preview_btn, &QPushButton::click);
+
+               connect(preview_btn, &QPushButton::clicked, [this, i]{ preview_angle_clicked(i); });
+       }
 }
 
 MainWindow::~MainWindow()
@@ -250,8 +258,7 @@ void MainWindow::queue_clicked()
 
        QModelIndex index = selected->currentIndex();
        Clip clip = *cliplist_clips->clip(index.row());
-       if (index.column() >= int(ClipList::Column::CAMERA_1) &&
-           index.column() <= int(ClipList::Column::CAMERA_4)) {
+       if (ClipList::is_camera_column(index.column())) {
                clip.stream_idx = index.column() - int(ClipList::Column::CAMERA_1);
        } else {
                clip.stream_idx = ui->preview_display->get_stream_idx();
@@ -293,8 +300,7 @@ void MainWindow::preview_clicked()
 
        QModelIndex index = selected->currentIndex();
        unsigned stream_idx;
-       if (index.column() >= int(ClipList::Column::CAMERA_1) &&
-           index.column() <= int(ClipList::Column::CAMERA_4)) {
+       if (ClipList::is_camera_column(index.column())) {
                stream_idx = index.column() - int(ClipList::Column::CAMERA_1);
        } else {
                stream_idx = ui->preview_display->get_stream_idx();
@@ -799,8 +805,7 @@ void MainWindow::playlist_selection_changed()
 void MainWindow::clip_list_selection_changed(const QModelIndex &current, const QModelIndex &)
 {
        int camera_selected = -1;
-       if (current.column() >= int(ClipList::Column::CAMERA_1) &&
-           current.column() <= int(ClipList::Column::CAMERA_4)) {
+       if (ClipList::is_camera_column(current.column())) {
                camera_selected = current.column() - int(ClipList::Column::CAMERA_1);
        }
        highlight_camera_input(camera_selected);
@@ -978,25 +983,12 @@ void MainWindow::quality_toggled(int quality, bool checked)
 
 void MainWindow::highlight_camera_input(int stream_idx)
 {
-       if (stream_idx == 0) {
-               ui->input1_frame->setStyleSheet("background: rgb(0,255,0)");
-       } else {
-               ui->input1_frame->setStyleSheet("");
-       }
-       if (stream_idx == 1) {
-               ui->input2_frame->setStyleSheet("background: rgb(0,255,0)");
-       } else {
-               ui->input2_frame->setStyleSheet("");
-       }
-       if (stream_idx == 2) {
-               ui->input3_frame->setStyleSheet("background: rgb(0,255,0)");
-       } else {
-               ui->input3_frame->setStyleSheet("");
-       }
-       if (stream_idx == 3) {
-               ui->input4_frame->setStyleSheet("background: rgb(0,255,0)");
-       } else {
-               ui->input4_frame->setStyleSheet("");
+       for (unsigned i = 0; i < NUM_CAMERAS; ++i) {
+               if (stream_idx == i) {
+                       displays[i].frame->setStyleSheet("background: rgb(0,255,0)");
+               } else {
+                       displays[i].frame->setStyleSheet("");
+               }
        }
 }
 
@@ -1013,6 +1005,13 @@ pair<string, string> MainWindow::get_queue_status() const {
        return {queue_status, "text/plain"};
 }
 
+void MainWindow::display_frame(unsigned stream_idx, const FrameOnDisk &frame)
+{
+       if (stream_idx < NUM_CAMERAS) {
+               displays[stream_idx].display->setFrame(stream_idx, frame);
+       }
+}
+
 template <class Model>
 void MainWindow::replace_model(QTableView *view, Model **model, Model *new_model)
 {
index 798745609b9ca7627aac96aff337f6cc0cae9f5e..97f0f296aef8638372635b13b14d0be019e2a923 100644 (file)
@@ -19,7 +19,10 @@ namespace Ui {
 class MainWindow;
 }  // namespace Ui
 
+struct FrameOnDisk;
+class JPEGFrameView;
 class Player;
+class QPushButton;
 class QTableView;
 
 class MainWindow : public QMainWindow {
@@ -32,10 +35,11 @@ public:
        // HTTP callback. TODO: Does perhaps not belong to MainWindow?
        std::pair<std::string, std::string> get_queue_status() const;
 
-//private:
-       Ui::MainWindow *ui;
+       void display_frame(unsigned stream_idx, const FrameOnDisk &frame);
 
 private:
+       Ui::MainWindow *ui;
+
        QLabel *disk_free_label;
        std::unique_ptr<Player> preview_player, live_player;
        DB db;
@@ -76,6 +80,13 @@ private:
        mutable std::mutex queue_status_mu;
        std::string queue_status;  // Under queue_status_mu.
 
+       struct FrameAndDisplay {
+               QFrame *frame;
+               JPEGFrameView *display;
+               QPushButton *preview_btn;
+       };
+       std::vector<FrameAndDisplay> displays;
+
        void cue_in_clicked();
        void cue_out_clicked();
        void queue_clicked();
index 288da89691fcc54ae97d296f4bb7f44ebe5e4e4b..212f3bd4c7365c0d1888d2059c83ae1c770d23f3 100644 (file)
              <string>Stop</string>
             </property>
             <property name="icon">
-             <iconset theme="media-playback-stop"/>
+             <iconset theme="media-playback-stop">
+              <normaloff>.</normaloff>.</iconset>
             </property>
            </widget>
           </item>
              <widget class="JPEGFrameView" name="preview_display" native="true"/>
             </item>
             <item>
-             <layout class="QHBoxLayout" name="horizontalLayout_3">
+             <layout class="QHBoxLayout" name="preview_layout">
               <property name="spacing">
                <number>0</number>
               </property>
                 </property>
                </widget>
               </item>
-              <item>
-               <widget class="QPushButton" name="preview_1_btn">
-                <property name="sizePolicy">
-                 <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
-                  <horstretch>0</horstretch>
-                  <verstretch>0</verstretch>
-                 </sizepolicy>
-                </property>
-                <property name="maximumSize">
-                 <size>
-                  <width>20</width>
-                  <height>17</height>
-                 </size>
-                </property>
-                <property name="text">
-                 <string>1</string>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <widget class="QPushButton" name="preview_2_btn">
-                <property name="sizePolicy">
-                 <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
-                  <horstretch>0</horstretch>
-                  <verstretch>0</verstretch>
-                 </sizepolicy>
-                </property>
-                <property name="maximumSize">
-                 <size>
-                  <width>20</width>
-                  <height>17</height>
-                 </size>
-                </property>
-                <property name="text">
-                 <string>2</string>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <widget class="QPushButton" name="preview_3_btn">
-                <property name="maximumSize">
-                 <size>
-                  <width>20</width>
-                  <height>17</height>
-                 </size>
-                </property>
-                <property name="text">
-                 <string>3</string>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <widget class="QPushButton" name="preview_4_btn">
-                <property name="maximumSize">
-                 <size>
-                  <width>20</width>
-                  <height>17</height>
-                 </size>
-                </property>
-                <property name="text">
-                 <string>4</string>
-                </property>
-               </widget>
-              </item>
              </layout>
             </item>
            </layout>
             <property name="spacing">
              <number>0</number>
             </property>
-            <item row="0" column="0">
-             <widget class="QFrame" name="input1_frame">
-              <property name="frameShape">
-               <enum>QFrame::Box</enum>
-              </property>
-              <property name="frameShadow">
-               <enum>QFrame::Plain</enum>
-              </property>
-              <property name="lineWidth">
-               <number>0</number>
-              </property>
-              <layout class="QGridLayout" name="gridLayout_2">
-               <property name="leftMargin">
-                <number>3</number>
-               </property>
-               <property name="topMargin">
-                <number>3</number>
-               </property>
-               <property name="rightMargin">
-                <number>3</number>
-               </property>
-               <property name="bottomMargin">
-                <number>3</number>
-               </property>
-               <item row="0" column="0">
-                <widget class="JPEGFrameView" name="input1_display" native="true">
-                 <property name="autoFillBackground">
-                  <bool>true</bool>
-                 </property>
-                </widget>
-               </item>
-              </layout>
-             </widget>
-            </item>
-            <item row="1" column="0">
-             <widget class="QFrame" name="input3_frame">
-              <property name="frameShape">
-               <enum>QFrame::Box</enum>
-              </property>
-              <property name="frameShadow">
-               <enum>QFrame::Plain</enum>
-              </property>
-              <property name="lineWidth">
-               <number>0</number>
-              </property>
-              <layout class="QGridLayout" name="gridLayout_4">
-               <property name="leftMargin">
-                <number>3</number>
-               </property>
-               <property name="topMargin">
-                <number>3</number>
-               </property>
-               <property name="rightMargin">
-                <number>3</number>
-               </property>
-               <property name="bottomMargin">
-                <number>3</number>
-               </property>
-               <item row="0" column="0">
-                <widget class="JPEGFrameView" name="input3_display" native="true"/>
-               </item>
-              </layout>
-             </widget>
-            </item>
-            <item row="0" column="1">
-             <widget class="QFrame" name="input2_frame">
-              <property name="frameShape">
-               <enum>QFrame::Box</enum>
-              </property>
-              <property name="frameShadow">
-               <enum>QFrame::Plain</enum>
-              </property>
-              <property name="lineWidth">
-               <number>0</number>
-              </property>
-              <layout class="QGridLayout" name="gridLayout_3">
-               <property name="leftMargin">
-                <number>3</number>
-               </property>
-               <property name="topMargin">
-                <number>3</number>
-               </property>
-               <property name="rightMargin">
-                <number>3</number>
-               </property>
-               <property name="bottomMargin">
-                <number>3</number>
-               </property>
-               <item row="0" column="0">
-                <widget class="JPEGFrameView" name="input2_display" native="true">
-                 <property name="autoFillBackground">
-                  <bool>true</bool>
-                 </property>
-                </widget>
-               </item>
-              </layout>
-             </widget>
-            </item>
-            <item row="1" column="1">
-             <widget class="QFrame" name="input4_frame">
-              <property name="autoFillBackground">
-               <bool>true</bool>
-              </property>
-              <property name="frameShape">
-               <enum>QFrame::Box</enum>
-              </property>
-              <property name="frameShadow">
-               <enum>QFrame::Plain</enum>
-              </property>
-              <property name="lineWidth">
-               <number>0</number>
-              </property>
-              <layout class="QGridLayout" name="gridLayout_5">
-               <property name="leftMargin">
-                <number>3</number>
-               </property>
-               <property name="topMargin">
-                <number>3</number>
-               </property>
-               <property name="rightMargin">
-                <number>3</number>
-               </property>
-               <property name="bottomMargin">
-                <number>3</number>
-               </property>
-               <item row="0" column="0">
-                <widget class="JPEGFrameView" name="input4_display" native="true"/>
-               </item>
-              </layout>
-             </widget>
-            </item>
            </layout>
           </item>
           <item>