#include "AbstractLogWindow.hpp" #include #include #include #include #include #include #include #include #include #include #include #include "Configuration.hpp" #include "SettingsGroup.hpp" #include "MessageBox.hpp" #include "models/FontOverrideModel.hpp" #include "pimpl_impl.hpp" class AbstractLogWindow::impl final : public QObject { Q_OBJECT public: impl (AbstractLogWindow * self, QString const& settings_key, QSettings * settings , Configuration const * configuration) : self_ {self} , settings_key_ {settings_key} , settings_ {settings} , configuration_ {configuration} , log_view_ {nullptr} { } void delete_QSOs (); AbstractLogWindow * self_; QString settings_key_; QSettings * settings_; Configuration const * configuration_; QTableView * log_view_; FontOverrideModel model_; }; #include "moc_AbstractLogWindow.cpp" #include "AbstractLogWindow.moc" namespace { bool row_is_higher (QModelIndex const& lhs, QModelIndex const& rhs) { return lhs.row () > rhs.row (); } } void AbstractLogWindow::impl::delete_QSOs () { auto selection_model = log_view_->selectionModel (); selection_model->select (selection_model->selection (), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); auto row_indexes = selection_model->selectedRows (); if (row_indexes.size () && MessageBox::Yes == MessageBox::query_message (self_ , tr ("Confirm Delete") , tr ("Are you sure you want to delete the %n " "selected QSO(s) from the log?", "" , row_indexes.size ()) , QString {} , MessageBox::Yes | MessageBox::No , MessageBox::No)) { // We must work with source model indexes because we don't want row // removes to invalidate model indexes we haven't yet processed. We // achieve that by processing them in descending row order. for (auto& row_index : row_indexes) { row_index = model_.mapToSource (row_index); } // reverse sort by row std::sort (row_indexes.begin (), row_indexes.end (), row_is_higher); for (auto index : row_indexes) { auto row = model_.mapFromSource(index).row(); model_.removeRow(row); self_->log_model_changed(); } } } AbstractLogWindow::AbstractLogWindow (QString const& settings_key, QSettings * settings , Configuration const * configuration , QWidget * parent) : QWidget {parent} , m_ {this, settings_key, settings, configuration} { // when we're viewing the log by contact ID (visually, up/down chevron in the column heading), // when we add a contact, scroll the list to the top or bottom, depending on the sort order. // If the table is sorted by some other criteria, don't change anything. connect(&m_->model_, &QAbstractItemModel::rowsInserted, this, [this](QModelIndex const &parent, int first, int last) { (void) (parent); // UNUSED (void) (first); // UNUSED (void) (last); // UNUSED QTimer::singleShot(0, [=] { // if we're sorting by the date, then show the most-recently logged contact. // Otherwise, leave the scroll alone auto horizontal_header = m_->log_view_->horizontalHeader (); if (horizontal_header->sortIndicatorSection() == 3) { // sorting on date? if (horizontal_header->sortIndicatorOrder() == Qt::AscendingOrder) { // we're sorting oldes->newest, so go to bottom m_->log_view_->scrollToBottom(); } else { m_->log_view_->scrollToTop(); } } }); } ); } AbstractLogWindow::~AbstractLogWindow () { SettingsGroup g {m_->settings_, m_->settings_key_}; m_->settings_->setValue ("window/geometry", saveGeometry ()); } void AbstractLogWindow::set_log_view (QTableView * log_view) { // do this here because we know the UI must be setup before this SettingsGroup g {m_->settings_, m_->settings_key_}; restoreGeometry (m_->settings_->value ("window/geometry").toByteArray ()); m_->log_view_ = log_view; set_log_view_font (m_->configuration_->decoded_text_font ()); log_view->setSortingEnabled (true); log_view->setContextMenuPolicy (Qt::ActionsContextMenu); log_view->setAlternatingRowColors (true); log_view->setSelectionBehavior (QAbstractItemView::SelectRows); log_view->setSelectionMode (QAbstractItemView::ExtendedSelection); log_view->setVerticalScrollMode (QAbstractItemView::ScrollPerPixel); m_->model_.setSourceModel (log_view->model ()); log_view->setModel (&m_->model_); log_view->setColumnHidden (0, true); // hide the ID column auto horizontal_header = log_view->horizontalHeader (); horizontal_header->setResizeContentsPrecision (0); // visible region only horizontal_header->setSectionResizeMode (QHeaderView::ResizeToContents); horizontal_header->setSectionsMovable (true); horizontal_header->setSortIndicator(3, Qt::AscendingOrder); // sort by the contact datetime oldest->newest auto vertical_header = log_view->horizontalHeader (); vertical_header->setResizeContentsPrecision (0); // visible region only vertical_header->setSectionResizeMode (QHeaderView::ResizeToContents); // actions auto delete_action = new QAction {tr ("&Delete ..."), log_view}; log_view->insertAction (nullptr, delete_action); connect (delete_action, &QAction::triggered, [this] (bool /*checked*/) { m_->delete_QSOs (); }); // scroll to bottom, since we're showing 1-N log_view->scrollToBottom(); } void AbstractLogWindow::set_log_view_font (QFont const& font) { m_->log_view_->setFont (font); m_->log_view_->horizontalHeader ()->setFont (font); m_->log_view_->verticalHeader ()->setFont (font); m_->model_.set_font (font); }