Skip to content

Commit 70556ab

Browse files
committed
GUI: пункты «Очистить таблицу» и «Удалить запись»
В контекстное меню списка таблиц добавлена очистка таблицы, в окно данных — удаление записи через контекстное меню. Обе операции с подтверждением, проверкой режима только-чтения и обновлением представления; опираются на пометку записей удалёнными в библиотеке.
1 parent 04f35d9 commit 70556ab

6 files changed

Lines changed: 146 additions & 2 deletions

File tree

src/gtool1cd/mainwindow.cpp

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include "configurations_window.h"
3232
#include "about_dialog.h"
3333
#include <QSortFilterProxyModel>
34+
#include <QMenu>
35+
#include <QMessageBox>
3436

3537
void MainWindow::AddDetailedMessage(
3638
const std::string &description,
@@ -70,7 +72,13 @@ void MainWindow::show_table_context_menu(const QPoint &pos)
7072
QAction action_import_blob(tr("Импорт BLOB"), this);
7173
connect(&action_import_blob, SIGNAL(triggered()), this, SLOT(import_blob_file()));
7274
contextMenu.addAction(&action_import_blob);
73-
75+
76+
contextMenu.addSeparator();
77+
78+
QAction action_clear_table(tr("Очистить таблицу"), this);
79+
connect(&action_clear_table, SIGNAL(triggered()), this, SLOT(clear_table_action()));
80+
contextMenu.addAction(&action_clear_table);
81+
7482
contextMenu.exec(mapToGlobal(pos));
7583
}
7684

@@ -109,6 +117,58 @@ void MainWindow::import_blob_file()
109117
}
110118
}
111119

120+
void MainWindow::clear_table_action()
121+
{
122+
auto indexes = ui->tableListView->selectionModel()->selectedIndexes();
123+
if (indexes.empty()) {
124+
return;
125+
}
126+
127+
auto *proxy = qobject_cast<QSortFilterProxyModel*>(ui->tableListView->model());
128+
QModelIndex src = proxy ? proxy->mapToSource(indexes.first()) : indexes.first();
129+
Table *t = db->get_table(src.row());
130+
131+
if (db->get_readonly()) {
132+
QMessageBox::warning(this, tr("Очистка таблицы"),
133+
tr("База открыта только для чтения — очистка невозможна."));
134+
return;
135+
}
136+
137+
if (QMessageBox::warning(this, tr("Очистка таблицы"),
138+
tr("Пометить удалёнными ВСЕ записи таблицы «%1»?\nДействие изменяет базу и необратимо.")
139+
.arg(QString::fromStdString(t->get_name())),
140+
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) {
141+
return;
142+
}
143+
144+
uint32_t deleted = 0;
145+
try {
146+
t->begin_edit();
147+
uint32_t total = t->get_phys_numrecords();
148+
for (uint32_t i = 1; i < total; i++) {
149+
auto *rec = t->get_record(i);
150+
bool removed = rec->is_removed();
151+
delete rec;
152+
if (!removed) {
153+
t->mark_record_removed(i);
154+
deleted++;
155+
}
156+
}
157+
db->flush();
158+
} catch (DetailedException &ex) {
159+
QMessageBox::critical(this, tr("Очистка таблицы"), QString(ex.what()));
160+
return;
161+
}
162+
163+
auto it = table_windows.find(t);
164+
if (it != table_windows.end()) {
165+
static_cast<TableDataWindow*>(it.value())->reload();
166+
}
167+
168+
QMessageBox::information(this, tr("Очистка таблицы"),
169+
tr("Готово. Помечено удалёнными записей: %1.").arg(deleted));
170+
}
171+
112172
MainWindow::~MainWindow()
113173
{
114174
delete ui;

src/gtool1cd/mainwindow.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,11 @@ private slots:
6767
void show_table_context_menu(const QPoint &);
6868

6969
void export_blob_file();
70-
70+
7171
void import_blob_file();
7272

73+
void clear_table_action();
74+
7375
private:
7476
Ui::MainWindow *ui;
7577
T_1CD *db;

src/gtool1cd/models/table_data_model.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,19 @@ const TableRecord *TableDataModel::getRecord(const QModelIndex &index) const
226226

227227
}
228228

229+
uint32_t TableDataModel::physicalRecordNo(const QModelIndex &index) const
230+
{
231+
return _index == nullptr
232+
? index.row()
233+
: _index->get_numrec(index.row());
234+
}
235+
236+
void TableDataModel::notifyRowChanged(int row)
237+
{
238+
emit dataChanged(index(row, 0, QModelIndex()),
239+
index(row, columnCount(QModelIndex()) - 1, QModelIndex()));
240+
}
241+
229242
TStream *TableDataModel::getBlobStream(const QModelIndex &index) const
230243
{
231244
Field *f = table->get_field(index.column());

src/gtool1cd/models/table_data_model.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ class TableDataModel : public QAbstractItemModel
5353

5454
const TableRecord *getRecord(const QModelIndex &index) const;
5555

56+
// Физический номер записи в таблице для строки модели
57+
uint32_t physicalRecordNo(const QModelIndex &index) const;
58+
59+
// Сообщить представлению, что строка изменилась (например, помечена удалённой)
60+
void notifyRowChanged(int row);
61+
5662
TStream *getBlobStream(const QModelIndex &index) const;
5763

5864
private:

src/gtool1cd/table_data_window.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include <QItemSelection>
3030
#include "models/skobka_tree_model.h"
3131
#include <QFileDialog>
32+
#include <QMenu>
33+
#include <QMessageBox>
3234
#include "models/v8catalog_tree_model.h"
3335

3436
QString index_presentation(Index *index)
@@ -81,6 +83,10 @@ TableDataWindow::TableDataWindow(QWidget *parent, Table *table)
8183
emit ui->indexChooseBox->activated(1);
8284
}
8385

86+
ui->dataView->setContextMenuPolicy(Qt::CustomContextMenu);
87+
connect(ui->dataView, SIGNAL(customContextMenuRequested(QPoint)),
88+
this, SLOT(show_data_context_menu(QPoint)));
89+
8490
ui->dataView->setFocus();
8591
}
8692

@@ -199,3 +205,54 @@ void TableDataWindow::on_saveBlobButton_clicked()
199205
auto model = static_cast<TableDataModel*>(ui->dataView->model());
200206
model->dumpBlob(index, filename);
201207
}
208+
209+
void TableDataWindow::reload()
210+
{
211+
on_indexChooseBox_activated(ui->indexChooseBox->currentIndex());
212+
}
213+
214+
void TableDataWindow::show_data_context_menu(const QPoint &pos)
215+
{
216+
if (!ui->dataView->currentIndex().isValid()) {
217+
return;
218+
}
219+
QMenu menu(this);
220+
QAction action_delete(tr("Удалить запись"), this);
221+
connect(&action_delete, SIGNAL(triggered()), this, SLOT(delete_record_action()));
222+
menu.addAction(&action_delete);
223+
menu.exec(ui->dataView->mapToGlobal(pos));
224+
}
225+
226+
void TableDataWindow::delete_record_action()
227+
{
228+
auto index = ui->dataView->currentIndex();
229+
if (!index.isValid()) {
230+
return;
231+
}
232+
auto *model = static_cast<TableDataModel*>(ui->dataView->model());
233+
uint32_t phys_numrecord = model->physicalRecordNo(index);
234+
235+
if (table->get_base()->get_readonly()) {
236+
QMessageBox::warning(this, tr("Удаление записи"),
237+
tr("База открыта только для чтения — удаление невозможно."));
238+
return;
239+
}
240+
241+
if (QMessageBox::warning(this, tr("Удаление записи"),
242+
tr("Пометить запись №%1 таблицы «%2» удалённой?\nДействие изменяет базу.")
243+
.arg(phys_numrecord).arg(QString::fromStdString(table->get_name())),
244+
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) {
245+
return;
246+
}
247+
248+
try {
249+
table->begin_edit();
250+
table->mark_record_removed(phys_numrecord);
251+
table->get_base()->flush();
252+
} catch (DetailedException &ex) {
253+
QMessageBox::critical(this, tr("Удаление записи"), QString(ex.what()));
254+
return;
255+
}
256+
257+
model->notifyRowChanged(index.row());
258+
}

src/gtool1cd/table_data_window.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,14 @@ class TableDataWindow : public QMainWindow
4040
explicit TableDataWindow(QWidget *parent, Table *table);
4141
~TableDataWindow();
4242

43+
void reload(); // перечитать данные таблицы в текущем представлении
44+
4345
private slots:
4446

47+
void show_data_context_menu(const QPoint &pos);
48+
49+
void delete_record_action();
50+
4551
void on_descriptionButton_clicked();
4652

4753
void on_fieldsButton_clicked();

0 commit comments

Comments
 (0)