annotate widgets/ModelDataTableDialog.cpp @ 1447:8afea53332f3 single-point

Add option to make pane sizes auto-resize-only (i.e. remove user control via a splitter); also place alignment views above panes instead of below, meaning the extra bit of space that we currently have for the pane without one at least goes to the primary pane
author Chris Cannam
date Tue, 30 Apr 2019 15:53:21 +0100
parents 0ded54e94332
children d39db4673676
rev   line source
Chris@392 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@392 2
Chris@392 3 /*
Chris@392 4 Sonic Visualiser
Chris@392 5 An audio file viewer and annotation editor.
Chris@392 6 Centre for Digital Music, Queen Mary, University of London.
Chris@392 7 This file copyright 2008 QMUL.
Chris@392 8
Chris@392 9 This program is free software; you can redistribute it and/or
Chris@392 10 modify it under the terms of the GNU General Public License as
Chris@392 11 published by the Free Software Foundation; either version 2 of the
Chris@392 12 License, or (at your option) any later version. See the file
Chris@392 13 COPYING included with this distribution for more information.
Chris@392 14 */
Chris@392 15
Chris@392 16 #include "ModelDataTableDialog.h"
Chris@392 17
Chris@392 18 #include "data/model/ModelDataTableModel.h"
Chris@395 19 #include "data/model/TabularModel.h"
Chris@398 20 #include "data/model/Model.h"
Chris@392 21
Chris@393 22 #include "CommandHistory.h"
Chris@399 23 #include "IconLoader.h"
Chris@393 24
Chris@392 25 #include <QTableView>
Chris@552 26 #include <QLineEdit>
Chris@392 27 #include <QGridLayout>
Chris@552 28 #include <QLabel>
Chris@392 29 #include <QGroupBox>
Chris@392 30 #include <QDialogButtonBox>
Chris@392 31 #include <QHeaderView>
Chris@392 32 #include <QApplication>
Chris@392 33 #include <QDesktopWidget>
Chris@399 34 #include <QAction>
Chris@399 35 #include <QToolBar>
Chris@392 36
Chris@393 37 #include <iostream>
Chris@393 38
Chris@404 39 ModelDataTableDialog::ModelDataTableDialog(TabularModel *model,
Chris@404 40 QString title, QWidget *parent) :
Chris@400 41 QMainWindow(parent),
Chris@401 42 m_currentRow(0),
Chris@404 43 m_trackPlayback(true)
Chris@392 44 {
Chris@392 45 setWindowTitle(tr("Data Editor"));
Chris@392 46
Chris@404 47 QToolBar *toolbar;
Chris@399 48
Chris@404 49 toolbar = addToolBar(tr("Playback Toolbar"));
Chris@404 50 m_playToolbar = toolbar;
Chris@404 51 toolbar = addToolBar(tr("Play Mode Toolbar"));
Chris@404 52
Chris@399 53 IconLoader il;
Chris@399 54
Chris@402 55 QAction *action = new QAction(il.load("playfollow"), tr("Track Playback"), this);
Chris@402 56 action->setStatusTip(tr("Toggle tracking of playback position"));
Chris@402 57 action->setCheckable(true);
Chris@404 58 action->setChecked(m_trackPlayback);
Chris@402 59 connect(action, SIGNAL(triggered()), this, SLOT(togglePlayTracking()));
Chris@402 60 toolbar->addAction(action);
Chris@402 61
Chris@404 62 toolbar = addToolBar(tr("Edit Toolbar"));
Chris@402 63
Chris@1175 64 action = new QAction(il.load("draw"), tr("Insert New Item"), this);
Chris@399 65 action->setShortcut(tr("Insert"));
Chris@399 66 action->setStatusTip(tr("Insert a new item"));
Chris@399 67 connect(action, SIGNAL(triggered()), this, SLOT(insertRow()));
Chris@399 68 toolbar->addAction(action);
Chris@399 69
Chris@399 70 action = new QAction(il.load("datadelete"), tr("Delete Selected Items"), this);
Chris@399 71 action->setShortcut(tr("Delete"));
Chris@399 72 action->setStatusTip(tr("Delete the selected item or items"));
Chris@400 73 connect(action, SIGNAL(triggered()), this, SLOT(deleteRows()));
Chris@399 74 toolbar->addAction(action);
Chris@399 75
Chris@404 76 CommandHistory::getInstance()->registerToolbar(toolbar);
Chris@404 77
Chris@404 78 /*
Chris@399 79 action = new QAction(il.load("dataedit"), tr("Edit Selected Item"), this);
Chris@399 80 action->setShortcut(tr("Edit"));
Chris@399 81 action->setStatusTip(tr("Edit the selected item"));
Chris@399 82 connect(action, SIGNAL(triggered()), this, SLOT(editRow()));
Chris@399 83 toolbar->addAction(action);
Chris@404 84 */
Chris@399 85
Chris@396 86 QFrame *mainFrame = new QFrame;
Chris@396 87 setCentralWidget(mainFrame);
Chris@396 88
Chris@392 89 QGridLayout *grid = new QGridLayout;
Chris@396 90 mainFrame->setLayout(grid);
Chris@392 91
Chris@392 92 QGroupBox *box = new QGroupBox;
Chris@398 93 if (title != "") {
Chris@398 94 box->setTitle(title);
Chris@398 95 } else {
Chris@398 96 box->setTitle(tr("Data in Layer"));
Chris@398 97 }
Chris@392 98 grid->addWidget(box, 0, 0);
Chris@392 99 grid->setRowStretch(0, 15);
Chris@392 100
Chris@392 101 QGridLayout *subgrid = new QGridLayout;
Chris@392 102 box->setLayout(subgrid);
Chris@392 103
Chris@392 104 subgrid->setSpacing(0);
Chris@392 105 subgrid->setMargin(5);
Chris@392 106
Chris@552 107 subgrid->addWidget(new QLabel(tr("Find:")), 1, 0);
Chris@552 108 subgrid->addWidget(new QLabel(tr(" ")), 1, 1);
Chris@552 109 m_find = new QLineEdit;
Chris@552 110 subgrid->addWidget(m_find, 1, 2);
Chris@552 111 connect(m_find, SIGNAL(textChanged(const QString &)),
Chris@552 112 this, SLOT(searchTextChanged(const QString &)));
Chris@552 113 connect(m_find, SIGNAL(returnPressed()),
Chris@552 114 this, SLOT(searchRepeated()));
Chris@552 115
Chris@392 116 m_tableView = new QTableView;
Chris@552 117 subgrid->addWidget(m_tableView, 0, 0, 1, 3);
Chris@392 118
Chris@395 119 m_tableView->setSortingEnabled(true);
Chris@396 120 m_tableView->sortByColumn(0, Qt::AscendingOrder);
Chris@392 121
Chris@392 122 m_table = new ModelDataTableModel(model);
Chris@392 123 m_tableView->setModel(m_table);
Chris@392 124
Chris@552 125 m_tableView->horizontalHeader()->setStretchLastSection(true);
Chris@552 126
Chris@393 127 connect(m_tableView, SIGNAL(clicked(const QModelIndex &)),
Chris@393 128 this, SLOT(viewClicked(const QModelIndex &)));
Chris@393 129 connect(m_tableView, SIGNAL(pressed(const QModelIndex &)),
Chris@393 130 this, SLOT(viewPressed(const QModelIndex &)));
Chris@400 131 connect(m_tableView->selectionModel(),
Chris@400 132 SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
Chris@400 133 this,
Chris@400 134 SLOT(currentChanged(const QModelIndex &, const QModelIndex &)));
Chris@400 135 connect(m_table, SIGNAL(addCommand(Command *)),
Chris@400 136 this, SLOT(addCommand(Command *)));
Chris@401 137 connect(m_table, SIGNAL(currentChanged(const QModelIndex &)),
Chris@401 138 this, SLOT(currentChangedThroughResort(const QModelIndex &)));
Chris@428 139 connect(m_table, SIGNAL(modelRemoved()),
Chris@428 140 this, SLOT(modelRemoved()));
Chris@393 141
Chris@392 142 QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Close);
Chris@396 143 connect(bb, SIGNAL(rejected()), this, SLOT(close()));
Chris@392 144 grid->addWidget(bb, 2, 0);
Chris@392 145 grid->setRowStretch(2, 0);
Chris@392 146
Chris@392 147 QDesktopWidget *desktop = QApplication::desktop();
Chris@392 148 QRect available = desktop->availableGeometry();
Chris@392 149
Chris@392 150 int width = available.width() / 3;
Chris@392 151 int height = available.height() / 2;
Chris@392 152 if (height < 370) {
Chris@392 153 if (available.height() > 500) height = 370;
Chris@392 154 }
Chris@552 155 if (width < 650) {
Chris@552 156 if (available.width() > 750) width = 650;
Chris@552 157 else if (width < 500) {
Chris@552 158 if (available.width() > 650) width = 500;
Chris@552 159 }
Chris@392 160 }
Chris@392 161
Chris@392 162 resize(width, height);
Chris@392 163 }
Chris@392 164
Chris@392 165 ModelDataTableDialog::~ModelDataTableDialog()
Chris@392 166 {
Chris@392 167 delete m_table;
Chris@392 168 }
Chris@392 169
Chris@393 170 void
Chris@908 171 ModelDataTableDialog::userScrolledToFrame(sv_frame_t frame)
Chris@393 172 {
Chris@401 173 QModelIndex index = m_table->getModelIndexForFrame(frame);
Chris@401 174 makeCurrent(index.row());
Chris@401 175 }
Chris@401 176
Chris@401 177 void
Chris@908 178 ModelDataTableDialog::playbackScrolledToFrame(sv_frame_t frame)
Chris@401 179 {
Chris@401 180 if (m_trackPlayback) {
Chris@401 181 QModelIndex index = m_table->getModelIndexForFrame(frame);
Chris@401 182 makeCurrent(index.row());
Chris@401 183 }
Chris@401 184 }
Chris@401 185
Chris@401 186 void
Chris@552 187 ModelDataTableDialog::searchTextChanged(const QString &text)
Chris@552 188 {
Chris@552 189 QModelIndex mi = m_table->findText(text);
Chris@552 190 if (mi.isValid()) {
Chris@552 191 makeCurrent(mi.row());
Chris@552 192 m_tableView->selectionModel()->setCurrentIndex
Chris@552 193 (mi, QItemSelectionModel::ClearAndSelect);
Chris@552 194 }
Chris@552 195 }
Chris@552 196
Chris@552 197 void
Chris@552 198 ModelDataTableDialog::searchRepeated()
Chris@552 199 {
Chris@552 200 QModelIndex mi = m_table->findText(m_find->text());
Chris@552 201 if (mi.isValid()) {
Chris@552 202 makeCurrent(mi.row());
Chris@552 203 m_tableView->selectionModel()->setCurrentIndex
Chris@552 204 (mi, QItemSelectionModel::ClearAndSelect);
Chris@552 205 }
Chris@552 206 }
Chris@552 207
Chris@552 208 void
Chris@401 209 ModelDataTableDialog::makeCurrent(int row)
Chris@401 210 {
Chris@1271 211 if (m_table->rowCount() == 0 ||
Chris@1271 212 row >= m_table->rowCount() ||
Chris@1271 213 row < 0) {
Chris@1271 214 return;
Chris@1271 215 }
Chris@1271 216
Chris@401 217 int rh = m_tableView->height() / m_tableView->rowHeight(0);
Chris@404 218 int topRow = row - rh/4;
Chris@401 219 if (topRow < 0) topRow = 0;
Chris@404 220
Chris@404 221 // should only scroll if the desired row is not currently visible
Chris@404 222
Chris@404 223 // should only select if no part of the desired row is currently selected
Chris@404 224
Chris@682 225 // cerr << "rh = " << rh << ", row = " << row << ", scrolling to "
Chris@682 226 // << topRow << endl;
Chris@404 227
Chris@404 228 int pos = m_tableView->rowViewportPosition(row);
Chris@404 229
Chris@404 230 if (pos < 0 || pos >= m_tableView->height() - rh) {
Chris@404 231 m_tableView->scrollTo(m_table->index(topRow, 0));
Chris@404 232 }
Chris@404 233
Chris@404 234 bool haveRowSelected = false;
Chris@404 235 for (int i = 0; i < m_table->columnCount(); ++i) {
Chris@404 236 if (m_tableView->selectionModel()->isSelected(m_table->index(row, i))) {
Chris@404 237 haveRowSelected = true;
Chris@404 238 break;
Chris@404 239 }
Chris@404 240 }
Chris@404 241
Chris@404 242 if (!haveRowSelected) {
Chris@404 243 m_tableView->selectionModel()->setCurrentIndex
Chris@404 244 (m_table->index(row, 0),
Chris@404 245 QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
Chris@404 246 }
Chris@393 247 }
Chris@393 248
Chris@393 249 void
Chris@393 250 ModelDataTableDialog::viewClicked(const QModelIndex &index)
Chris@393 251 {
Chris@587 252 // SVDEBUG << "ModelDataTableDialog::viewClicked: " << index.row() << ", " << index.column() << endl;
Chris@394 253 emit scrollToFrame(m_table->getFrameForModelIndex(index));
Chris@393 254 }
Chris@393 255
Chris@393 256 void
Chris@807 257 ModelDataTableDialog::viewPressed(const QModelIndex &)
Chris@393 258 {
Chris@587 259 // SVDEBUG << "ModelDataTableDialog::viewPressed: " << index.row() << ", " << index.column() << endl;
Chris@393 260 }
Chris@393 261
Chris@393 262 void
Chris@400 263 ModelDataTableDialog::currentChanged(const QModelIndex &current,
Chris@1272 264 const QModelIndex &previous)
Chris@399 265 {
Chris@1272 266 SVDEBUG << "ModelDataTableDialog::currentChanged: from "
Chris@1272 267 << previous.row() << ", " << previous.column()
Chris@1272 268 << " to " << current.row() << ", " << current.column()
Chris@1272 269 << endl;
Chris@400 270 m_currentRow = current.row();
Chris@401 271 m_table->setCurrentRow(m_currentRow);
Chris@399 272 }
Chris@399 273
Chris@399 274 void
Chris@400 275 ModelDataTableDialog::insertRow()
Chris@399 276 {
Chris@400 277 m_table->insertRow(m_currentRow);
Chris@400 278 }
Chris@400 279
Chris@400 280 void
Chris@400 281 ModelDataTableDialog::deleteRows()
Chris@400 282 {
Chris@1272 283 std::set<int> selectedRows;
Chris@1272 284 if (m_tableView->selectionModel()->hasSelection()) {
Chris@1272 285 for (const auto &ix: m_tableView->selectionModel()->selectedIndexes()) {
Chris@1272 286 selectedRows.insert(ix.row());
Chris@1272 287 }
Chris@1272 288 }
Chris@1272 289 // Remove rows in reverse order, so as not to pull the rug from
Chris@1272 290 // under our own feet
Chris@1272 291 for (auto ri = selectedRows.rbegin(); ri != selectedRows.rend(); ++ri) {
Chris@1272 292 SVDEBUG << "ModelDataTableDialog: removing row " << *ri << endl;
Chris@1272 293 m_table->removeRow(*ri);
Chris@400 294 }
Chris@399 295 }
Chris@399 296
Chris@399 297 void
Chris@399 298 ModelDataTableDialog::editRow()
Chris@399 299 {
Chris@399 300 }
Chris@399 301
Chris@399 302 void
Chris@400 303 ModelDataTableDialog::addCommand(Command *command)
Chris@393 304 {
Chris@397 305 CommandHistory::getInstance()->addCommand(command, false, true);
Chris@393 306 }
Chris@393 307
Chris@401 308 void
Chris@402 309 ModelDataTableDialog::togglePlayTracking()
Chris@402 310 {
Chris@402 311 m_trackPlayback = !m_trackPlayback;
Chris@402 312 }
Chris@402 313
Chris@402 314 void
Chris@401 315 ModelDataTableDialog::currentChangedThroughResort(const QModelIndex &index)
Chris@401 316 {
Chris@587 317 // SVDEBUG << "ModelDataTableDialog::currentChangedThroughResort: row = " << index.row() << endl;
Chris@401 318 // m_tableView->scrollTo(index);
Chris@401 319 makeCurrent(index.row());
Chris@401 320 }
Chris@401 321
Chris@428 322 void
Chris@428 323 ModelDataTableDialog::modelRemoved()
Chris@428 324 {
Chris@428 325 close();
Chris@428 326 }
Chris@401 327
Chris@401 328