From 70c6087e94ed2a12adffb283795482088a9a90c8 Mon Sep 17 00:00:00 2001 From: Mike Gelfand Date: Sun, 14 Dec 2014 18:12:21 +0000 Subject: [PATCH] Rework torrent details dialog in Qt client to load from .ui Make squeeze labels (used for values on Information tab) display tooltip on hover if their text doesn't fit. Make selective labels (same as in GTK+ client) text selectable with keyboard in addition to mouse. Prevent dialog width growth occured before to fit long error texts. --- qt/CMakeLists.txt | 1 + qt/details.cc | 499 ++++++++---------------- qt/details.h | 75 +--- qt/details.ui | 936 +++++++++++++++++++++++++++++++++++++++++++++ qt/qtr.pro | 3 +- qt/squeezelabel.cc | 19 +- qt/squeezelabel.h | 1 - 7 files changed, 1110 insertions(+), 424 deletions(-) create mode 100644 qt/details.ui diff --git a/qt/CMakeLists.txt b/qt/CMakeLists.txt index b916a770b..11870504e 100644 --- a/qt/CMakeLists.txt +++ b/qt/CMakeLists.txt @@ -101,6 +101,7 @@ set(${PROJECT_NAME}_HEADERS ) tr_qt_wrap_ui(${PROJECT_NAME}_UI_SOURCES + details.ui mainwin.ui ) diff --git a/qt/details.cc b/qt/details.cc index cd3a15d83..c8ee27920 100644 --- a/qt/details.cc +++ b/qt/details.cc @@ -11,17 +11,11 @@ #include /* INT_MAX */ #include -#include -#include #include #include -#include -#include #include #include #include -#include -#include #include #include #include @@ -30,18 +24,10 @@ #include #include #include -#include -#include #include -#include #include #include -#include -#include -#include -#include #include -#include #include #include // tr_getRatio () @@ -58,6 +44,7 @@ #include "tracker-delegate.h" #include "tracker-model.h" #include "tracker-model-filter.h" +#include "utils.h" class Prefs; class Session; @@ -83,6 +70,16 @@ namespace COL_CLIENT, N_COLUMNS }; + + int + measureViewItem (QAbstractItemView * view, const QString& text) + { + QStyleOptionViewItemV4 option; + option.features = QStyleOptionViewItemV2::HasDisplay; + option.text = text; + return view->style ()->sizeFromContents (QStyle::CT_ItemViewItem, &option, + QSize (QWIDGETSIZE_MAX, QWIDGETSIZE_MAX), view).width (); + } } /*** @@ -184,28 +181,18 @@ Details::Details (Session & session, myChangedTorrents (false), myHavePendingRefresh (false) { - QVBoxLayout * layout = new QVBoxLayout (this); - - setWindowTitle (tr ("Torrent Properties")); - - QTabWidget * t = new QTabWidget (this); - QWidget * w; - t->addTab (w = createInfoTab (), tr ("Information")); - myWidgets << w; - t->addTab (w = createPeersTab (), tr ("Peers")); - myWidgets << w; - t->addTab (w = createTrackerTab (), tr ("Tracker")); - myWidgets << w; - t->addTab (w = createFilesTab (), tr ("Files")); - myWidgets << w; - t->addTab (w = createOptionsTab (), tr ("Options")); - myWidgets << w; - layout->addWidget (t); - - QDialogButtonBox * buttons = new QDialogButtonBox (QDialogButtonBox::Close, Qt::Horizontal, this); - connect (buttons, SIGNAL (rejected ()), this, SLOT (close ())); - layout->addWidget (buttons); - QWidget::setAttribute (Qt::WA_DeleteOnClose, true); + ui.setupUi(this); + + initInfoTab (); + initPeersTab (); + initTrackerTab (); + initFilesTab (); + initOptionsTab (); + + adjustSize (); + ui.commentBrowser->setMaximumHeight (QWIDGETSIZE_MAX); + + setAttribute (Qt::WA_DeleteOnClose, true); QList initKeys; initKeys << Prefs::SHOW_TRACKER_SCRAPES @@ -244,7 +231,7 @@ Details::setIds (const QSet& ids) disconnect (tor, SIGNAL (torrentChanged (int)), this, SLOT (onTorrentChanged ())); } - myFileTreeView->clear (); + ui.filesView->clear (); myIds = ids; myTrackerModel->refresh (myModel, myIds); @@ -256,8 +243,8 @@ Details::setIds (const QSet& ids) connect (tor, SIGNAL (torrentChanged (int)), this, SLOT (onTorrentChanged ())); } - foreach (QWidget * w, myWidgets) - w->setEnabled (false); + for (int i = 0; i < ui.tabs->count (); ++i) + ui.tabs->widget (i)->setEnabled (false); onTimer (); } @@ -271,12 +258,12 @@ Details::refreshPref (int key) { case Prefs::SHOW_TRACKER_SCRAPES: { - QItemSelectionModel * selectionModel (myTrackerView->selectionModel ()); + QItemSelectionModel * selectionModel (ui.trackersView->selectionModel ()); const QItemSelection selection (selectionModel->selection ()); const QModelIndex currentIndex (selectionModel->currentIndex ()); myTrackerDelegate->setShowMore (myPrefs.getBool (key)); selectionModel->clear (); - myTrackerView->reset (); + ui.trackersView->reset (); selectionModel->select (selection, QItemSelectionModel::Select); selectionModel->setCurrentIndex (currentIndex, QItemSelectionModel::NoUpdate); break; @@ -429,7 +416,7 @@ Details::refresh () else string = torrents[0]->activityString (); } - myStateLabel->setText (string); + ui.stateValueLabel->setText (string); const QString stateString = string; // myHaveLabel @@ -487,7 +474,7 @@ Details::refresh () .arg (Formatter::sizeToString (haveUnverified)); } } - myHaveLabel->setText (string); + ui.haveValueLabel->setText (string); // myAvailabilityLabel if (torrents.empty ()) @@ -496,7 +483,7 @@ Details::refresh () string = none; else string = QString ("%1%").arg (Formatter::percentToString ( (100.0 * available) / sizeWhenDone)); - myAvailabilityLabel->setText (string); + ui.availabilityValueLabel->setText (string); // myDownloadedLabel if (torrents.empty ()) @@ -519,7 +506,7 @@ Details::refresh () else string = dstr; } - myDownloadedLabel->setText (string); + ui.downloadedValueLabel->setText (string); // myUploadedLabel if (torrents.empty ()) @@ -539,7 +526,7 @@ Details::refresh () .arg (Formatter::sizeToString (u)) .arg (Formatter::ratioToString (tr_getRatio (u, d))); } - myUploadedLabel->setText (string); + ui.uploadedValueLabel->setText (string); const QDateTime qdt_now = QDateTime::currentDateTime (); @@ -567,7 +554,7 @@ Details::refresh () else string = Formatter::timeToString (baseline.secsTo (qdt_now)); } - myRunTimeLabel->setText (string); + ui.runningTimeValueLabel->setText (string); // myETALabel @@ -596,7 +583,7 @@ Details::refresh () string = Formatter::timeToString (baseline); } } - myETALabel->setText (string); + ui.remainingTimeValueLabel->setText (string); // myLastActivityLabel @@ -622,7 +609,7 @@ Details::refresh () else string = tr ("%1 ago").arg (Formatter::timeToString (seconds)); } - myLastActivityLabel->setText (string); + ui.lastActivityValueLabel->setText (string); if (torrents.empty ()) @@ -643,7 +630,7 @@ Details::refresh () } if (string.isEmpty ()) string = none; - myErrorLabel->setText (string); + ui.errorValueLabel->setText (string); /// @@ -678,7 +665,7 @@ Details::refresh () string = tr ("%1 (%Ln pieces)", "", pieces) .arg (Formatter::sizeToString (size)); } - mySizeLabel->setText (string); + ui.sizeValueLabel->setText (string); // myHashLabel string = none; @@ -694,7 +681,7 @@ Details::refresh () } } } - myHashLabel->setText (string); + ui.hashValueLabel->setText (string); // myPrivacyLabel string = none; @@ -712,10 +699,11 @@ Details::refresh () } } } - myPrivacyLabel->setText (string); + ui.privacyValueLabel->setText (string); // myCommentBrowser string = none; + bool isCommentMixed = false; if (!torrents.empty ()) { string = torrents[0]->comment (); @@ -724,15 +712,16 @@ Details::refresh () if (string != t->comment ()) { string = mixed; + isCommentMixed = true; break; } } } - if (myCommentBrowser->toPlainText() != string) + if (ui.commentBrowser->toPlainText() != string) { - myCommentBrowser->setText (string); - myCommentBrowser->setMaximumHeight (QWIDGETSIZE_MAX); + ui.commentBrowser->setText (string); } + ui.commentBrowser->setEnabled (!isCommentMixed && !string.isEmpty ()); // myOriginLabel string = none; @@ -758,7 +747,7 @@ Details::refresh () else string = tr ("Created by %1 on %2").arg (creator).arg (date); } - myOriginLabel->setText (string); + ui.originValueLabel->setText (string); // myLocationLabel string = none; @@ -774,7 +763,7 @@ Details::refresh () } } } - myLocationLabel->setText (string); + ui.locationValueLabel->setText (string); /// @@ -794,33 +783,33 @@ Details::refresh () uniform = true; baselineFlag = baseline->honorsSessionLimits (); foreach (tor, torrents) if (baselineFlag != tor->honorsSessionLimits ()) { uniform = false; break; } - mySessionLimitCheck->setChecked (uniform && baselineFlag); + ui.sessionLimitCheck->setChecked (uniform && baselineFlag); // mySingleDownCheck uniform = true; baselineFlag = baseline->downloadIsLimited (); foreach (tor, torrents) if (baselineFlag != tor->downloadIsLimited ()) { uniform = false; break; } - mySingleDownCheck->setChecked (uniform && baselineFlag); + ui.singleDownCheck->setChecked (uniform && baselineFlag); // mySingleUpCheck uniform = true; baselineFlag = baseline->uploadIsLimited (); foreach (tor, torrents) if (baselineFlag != tor->uploadIsLimited ()) { uniform = false; break; } - mySingleUpCheck->setChecked (uniform && baselineFlag); + ui.singleUpCheck->setChecked (uniform && baselineFlag); // myBandwidthPriorityCombo uniform = true; baselineInt = baseline->getBandwidthPriority (); foreach (tor, torrents) if (baselineInt != tor->getBandwidthPriority ()) { uniform = false; break; } if (uniform) - i = myBandwidthPriorityCombo->findData (baselineInt); + i = ui.bandwidthPriorityCombo->findData (baselineInt); else i = -1; - setIfIdle (myBandwidthPriorityCombo, i); + setIfIdle (ui.bandwidthPriorityCombo, i); - setIfIdle (mySingleDownSpin, int (tor->downloadLimit ().KBps ())); - setIfIdle (mySingleUpSpin, int (tor->uploadLimit ().KBps ())); - setIfIdle (myPeerLimitSpin, tor->peerLimit ()); + setIfIdle (ui.singleDownSpin, int (tor->downloadLimit ().KBps ())); + setIfIdle (ui.singleUpSpin, int (tor->uploadLimit ().KBps ())); + setIfIdle (ui.peerLimitSpin, tor->peerLimit ()); } if (!torrents.empty ()) @@ -832,20 +821,20 @@ Details::refresh () int baselineInt = torrents[0]->seedRatioMode (); foreach (tor, torrents) if (baselineInt != tor->seedRatioMode ()) { uniform = false; break; } - setIfIdle (myRatioCombo, uniform ? myRatioCombo->findData (baselineInt) : -1); - myRatioSpin->setVisible (uniform && (baselineInt == TR_RATIOLIMIT_SINGLE)); + setIfIdle (ui.ratioCombo, uniform ? ui.ratioCombo->findData (baselineInt) : -1); + ui.ratioSpin->setVisible (uniform && (baselineInt == TR_RATIOLIMIT_SINGLE)); - setIfIdle (myRatioSpin, tor->seedRatioLimit ()); + setIfIdle (ui.ratioSpin, tor->seedRatioLimit ()); // idle uniform = true; baselineInt = torrents[0]->seedIdleMode (); foreach (tor, torrents) if (baselineInt != tor->seedIdleMode ()) { uniform = false; break; } - setIfIdle (myIdleCombo, uniform ? myIdleCombo->findData (baselineInt) : -1); - myIdleSpin->setVisible (uniform && (baselineInt == TR_RATIOLIMIT_SINGLE)); + setIfIdle (ui.idleCombo, uniform ? ui.idleCombo->findData (baselineInt) : -1); + ui.idleSpin->setVisible (uniform && (baselineInt == TR_RATIOLIMIT_SINGLE)); - setIfIdle (myIdleSpin, tor->seedIdleLimit ()); + setIfIdle (ui.idleSpin, tor->seedIdleLimit ()); } /// @@ -926,73 +915,38 @@ Details::refresh () } } - myPeerTree->addTopLevelItems (newItems); + ui.peersView->addTopLevelItems (newItems); foreach (QString key, myPeers.keys ()) { if (!peers2.contains (key)) // old peer has disconnected { QTreeWidgetItem * item = myPeers.value (key, 0); - myPeerTree->takeTopLevelItem (myPeerTree->indexOfTopLevelItem (item)); + ui.peersView->takeTopLevelItem (ui.peersView->indexOfTopLevelItem (item)); delete item; } } myPeers = peers2; if (!single) - myFileTreeView->clear (); + ui.filesView->clear (); if (single) - myFileTreeView->update (torrents[0]->files (), myChangedTorrents); + ui.filesView->update (torrents[0]->files (), myChangedTorrents); myChangedTorrents = false; myHavePendingRefresh = false; - foreach (QWidget * w, myWidgets) - w->setEnabled (true); -} - -void -Details::enableWhenChecked (QCheckBox * box, QWidget * w) -{ - connect (box, SIGNAL (toggled (bool)), w, SLOT (setEnabled (bool))); - w->setEnabled (box->isChecked ()); + for (int i = 0; i < ui.tabs->count (); ++i) + ui.tabs->widget (i)->setEnabled (true); } - /*** **** ***/ -QWidget * -Details::createInfoTab () +void +Details::initInfoTab () { - HIG * hig = new HIG (this); - - hig->addSectionTitle (tr ("Activity")); - hig->addRow (tr ("Have:"), myHaveLabel = new SqueezeLabel); - hig->addRow (tr ("Availability:"), myAvailabilityLabel = new SqueezeLabel); - hig->addRow (tr ("Uploaded:"), myUploadedLabel = new SqueezeLabel); - hig->addRow (tr ("Downloaded:"), myDownloadedLabel = new SqueezeLabel); - hig->addRow (tr ("State:"), myStateLabel = new SqueezeLabel); - hig->addRow (tr ("Running time:"), myRunTimeLabel = new SqueezeLabel); - hig->addRow (tr ("Remaining time:"), myETALabel = new SqueezeLabel); - hig->addRow (tr ("Last activity:"), myLastActivityLabel = new SqueezeLabel); - hig->addRow (tr ("Error:"), myErrorLabel = new SqueezeLabel); - hig->addSectionDivider (); - - hig->addSectionDivider (); - hig->addSectionTitle (tr ("Details")); - hig->addRow (tr ("Size:"), mySizeLabel = new SqueezeLabel); - hig->addRow (tr ("Location:"), myLocationLabel = new SqueezeLabel); - hig->addRow (tr ("Hash:"), myHashLabel = new SqueezeLabel); - hig->addRow (tr ("Privacy:"), myPrivacyLabel = new SqueezeLabel); - hig->addRow (tr ("Origin:"), myOriginLabel = new SqueezeLabel); - myOriginLabel->setMinimumWidth (325); // stop long origin strings from resizing the widgit - hig->addRow (tr ("Comment:"), myCommentBrowser = new QTextBrowser); - const int h = QFontMetrics (myCommentBrowser->font ()).lineSpacing () * 4; - myCommentBrowser->setFixedHeight (h); - - hig->finish (); - - return hig; + const int h = QFontMetrics (ui.commentBrowser->font ()).lineSpacing () * 4; + ui.commentBrowser->setFixedHeight (h); } /*** @@ -1046,7 +1000,7 @@ Details::onUploadLimitedToggled (bool val) void Details::onIdleModeChanged (int index) { - const int val = myIdleCombo->itemData (index).toInt (); + const int val = ui.idleCombo->itemData (index).toInt (); mySession.torrentSet (myIds, TR_KEY_seedIdleMode, val); getNewData (); } @@ -1054,7 +1008,7 @@ Details::onIdleModeChanged (int index) void Details::onRatioModeChanged (int index) { - const int val = myRatioCombo->itemData (index).toInt (); + const int val = ui.ratioCombo->itemData (index).toInt (); mySession.torrentSet (myIds, TR_KEY_seedRatioMode, val); } @@ -1063,7 +1017,7 @@ Details::onBandwidthPriorityChanged (int index) { if (index != -1) { - const int priority = myBandwidthPriorityCombo->itemData (index).toInt (); + const int priority = ui.bandwidthPriorityCombo->itemData (index).toInt (); mySession.torrentSet (myIds, TR_KEY_bandwidthPriority, priority); getNewData (); } @@ -1072,9 +1026,9 @@ Details::onBandwidthPriorityChanged (int index) void Details::onTrackerSelectionChanged () { - const int selectionCount = myTrackerView->selectionModel ()->selectedRows ().size (); - myEditTrackerButton->setEnabled (selectionCount == 1); - myRemoveTrackerButton->setEnabled (selectionCount > 0); + const int selectionCount = ui.trackersView->selectionModel ()->selectedRows ().size (); + ui.editTrackerButton->setEnabled (selectionCount == 1); + ui.removeTrackerButton->setEnabled (selectionCount > 0); } void @@ -1118,11 +1072,11 @@ Details::onAddTrackerClicked () void Details::onEditTrackerClicked () { - QItemSelectionModel * selectionModel = myTrackerView->selectionModel (); + QItemSelectionModel * selectionModel = ui.trackersView->selectionModel (); QModelIndexList selectedRows = selectionModel->selectedRows (); assert (selectedRows.size () == 1); QModelIndex i = selectionModel->currentIndex (); - const TrackerInfo trackerInfo = myTrackerView->model ()->data (i, TrackerModel::TrackerRole).value (); + const TrackerInfo trackerInfo = ui.trackersView->model ()->data (i, TrackerModel::TrackerRole).value (); bool ok = false; const QString newval = QInputDialog::getText (this, @@ -1155,12 +1109,12 @@ void Details::onRemoveTrackerClicked () { // make a map of torrentIds to announce URLs to remove - QItemSelectionModel * selectionModel = myTrackerView->selectionModel (); + QItemSelectionModel * selectionModel = ui.trackersView->selectionModel (); QModelIndexList selectedRows = selectionModel->selectedRows (); QMap torrentId_to_trackerIds; foreach (QModelIndex i, selectedRows) { - const TrackerInfo inf = myTrackerView->model ()->data (i, TrackerModel::TrackerRole).value (); + const TrackerInfo inf = ui.trackersView->model ()->data (i, TrackerModel::TrackerRole).value (); torrentId_to_trackerIds.insertMulti (inf.torrentId, inf.st.id); } @@ -1176,253 +1130,110 @@ Details::onRemoveTrackerClicked () getNewData (); } -QWidget * -Details::createOptionsTab () +void +Details::initOptionsTab () { - QSpinBox * s; - QCheckBox * c; - QComboBox * m; - QHBoxLayout * h; - QDoubleSpinBox * ds; const QString speed_K_str = Formatter::unitStr (Formatter::SPEED, Formatter::KB); - HIG * hig = new HIG (this); - hig->addSectionTitle (tr ("Speed")); - - c = new QCheckBox (tr ("Honor global &limits")); - mySessionLimitCheck = c; - hig->addWideControl (c); - connect (c, SIGNAL (clicked (bool)), this, SLOT (onHonorsSessionLimitsToggled (bool))); - - c = new QCheckBox (tr ("Limit &download speed (%1):").arg (speed_K_str)); - mySingleDownCheck = c; - s = new QSpinBox (); - s->setProperty (PREF_KEY, TR_KEY_downloadLimit); - s->setSingleStep (5); - s->setRange (0, INT_MAX); - mySingleDownSpin = s; - hig->addRow (c, s); - enableWhenChecked (c, s); - connect (c, SIGNAL (clicked (bool)), this, SLOT (onDownloadLimitedToggled (bool))); - connect (s, SIGNAL (editingFinished ()), this, SLOT (onSpinBoxEditingFinished ())); - - c = new QCheckBox (tr ("Limit &upload speed (%1):").arg (speed_K_str)); - mySingleUpCheck = c; - s = new QSpinBox (); - s->setSingleStep (5); - s->setRange (0, INT_MAX); - s->setProperty (PREF_KEY, TR_KEY_uploadLimit); - mySingleUpSpin = s; - hig->addRow (c, s); - enableWhenChecked (c, s); - connect (c, SIGNAL (clicked (bool)), this, SLOT (onUploadLimitedToggled (bool))); - connect (s, SIGNAL (editingFinished ()), this, SLOT (onSpinBoxEditingFinished ())); - - m = new QComboBox; - m->addItem (tr ("High"), TR_PRI_HIGH); - m->addItem (tr ("Normal"), TR_PRI_NORMAL); - m->addItem (tr ("Low"), TR_PRI_LOW); - connect (m, SIGNAL (currentIndexChanged (int)), this, SLOT (onBandwidthPriorityChanged (int))); - hig->addRow (tr ("Torrent &priority:"), m); - myBandwidthPriorityCombo = m; - - hig->addSectionDivider (); - hig->addSectionTitle (tr ("Seeding Limits")); - - h = new QHBoxLayout (); - h->setSpacing (HIG::PAD); - m = new QComboBox; - m->addItem (tr ("Use Global Settings"), TR_RATIOLIMIT_GLOBAL); - m->addItem (tr ("Seed regardless of ratio"), TR_RATIOLIMIT_UNLIMITED); - m->addItem (tr ("Stop seeding at ratio:"), TR_RATIOLIMIT_SINGLE); - connect (m, SIGNAL (currentIndexChanged (int)), this, SLOT (onRatioModeChanged (int))); - h->addWidget (myRatioCombo = m); - ds = new QDoubleSpinBox (); - ds->setRange (0.5, INT_MAX); - ds->setProperty (PREF_KEY, TR_KEY_seedRatioLimit); - connect (ds, SIGNAL (editingFinished ()), this, SLOT (onSpinBoxEditingFinished ())); - h->addWidget (myRatioSpin = ds); - hig->addRow (tr ("&Ratio:"), h, m); - - h = new QHBoxLayout (); - h->setSpacing (HIG::PAD); - m = new QComboBox; - m->addItem (tr ("Use Global Settings"), TR_IDLELIMIT_GLOBAL); - m->addItem (tr ("Seed regardless of activity"), TR_IDLELIMIT_UNLIMITED); - m->addItem (tr ("Stop seeding if idle for N minutes:"), TR_IDLELIMIT_SINGLE); - connect (m, SIGNAL (currentIndexChanged (int)), this, SLOT (onIdleModeChanged (int))); - h->addWidget (myIdleCombo = m); - s = new QSpinBox (); - s->setSingleStep (5); - s->setRange (1, 9999); - s->setProperty (PREF_KEY, TR_KEY_seedIdleLimit); - connect (s, SIGNAL (editingFinished ()), this, SLOT (onSpinBoxEditingFinished ())); - h->addWidget (myIdleSpin = s); - hig->addRow (tr ("&Idle:"), h, m); - - - hig->addSectionDivider (); - hig->addSectionTitle (tr ("Peer Connections")); - - s = new QSpinBox (); - s->setSingleStep (5); - s->setRange (1, 300); - s->setProperty (PREF_KEY, TR_KEY_peer_limit); - connect (s, SIGNAL (editingFinished ()), this, SLOT (onSpinBoxEditingFinished ())); - myPeerLimitSpin = s; - hig->addRow (tr ("&Maximum peers:"), s); - - hig->finish (); - - return hig; + ui.singleDownCheck->setText (ui.singleDownCheck->text ().arg(speed_K_str)); + ui.singleUpCheck->setText (ui.singleUpCheck->text ().arg(speed_K_str)); + + ui.singleDownSpin->setProperty (PREF_KEY, TR_KEY_downloadLimit); + ui.singleUpSpin->setProperty (PREF_KEY, TR_KEY_uploadLimit); + ui.ratioSpin->setProperty (PREF_KEY, TR_KEY_seedRatioLimit); + ui.idleSpin->setProperty (PREF_KEY, TR_KEY_seedIdleLimit); + ui.peerLimitSpin->setProperty (PREF_KEY, TR_KEY_peer_limit); + + ui.bandwidthPriorityCombo->addItem (tr ("High"), TR_PRI_HIGH); + ui.bandwidthPriorityCombo->addItem (tr ("Normal"), TR_PRI_NORMAL); + ui.bandwidthPriorityCombo->addItem (tr ("Low"), TR_PRI_LOW); + + ui.ratioCombo->addItem (tr ("Use Global Settings"), TR_RATIOLIMIT_GLOBAL); + ui.ratioCombo->addItem (tr ("Seed regardless of ratio"), TR_RATIOLIMIT_UNLIMITED); + ui.ratioCombo->addItem (tr ("Stop seeding at ratio:"), TR_RATIOLIMIT_SINGLE); + + ui.idleCombo->addItem (tr ("Use Global Settings"), TR_IDLELIMIT_GLOBAL); + ui.idleCombo->addItem (tr ("Seed regardless of activity"), TR_IDLELIMIT_UNLIMITED); + ui.idleCombo->addItem (tr ("Stop seeding if idle for N minutes:"), TR_IDLELIMIT_SINGLE); + + connect (ui.sessionLimitCheck, SIGNAL (clicked (bool)), SLOT (onHonorsSessionLimitsToggled (bool))); + connect (ui.singleDownCheck, SIGNAL (clicked (bool)), SLOT (onDownloadLimitedToggled (bool))); + connect (ui.singleDownSpin, SIGNAL (editingFinished ()), SLOT (onSpinBoxEditingFinished ())); + connect (ui.singleUpCheck, SIGNAL (clicked (bool)), SLOT (onUploadLimitedToggled (bool))); + connect (ui.singleUpSpin, SIGNAL (editingFinished ()), SLOT (onSpinBoxEditingFinished ())); + connect (ui.bandwidthPriorityCombo, SIGNAL (currentIndexChanged (int)), SLOT (onBandwidthPriorityChanged (int))); + connect (ui.ratioCombo, SIGNAL (currentIndexChanged (int)), SLOT (onRatioModeChanged (int))); + connect (ui.ratioSpin, SIGNAL (editingFinished ()), SLOT (onSpinBoxEditingFinished ())); + connect (ui.idleCombo, SIGNAL (currentIndexChanged (int)), SLOT (onIdleModeChanged (int))); + connect (ui.idleSpin, SIGNAL (editingFinished ()), SLOT (onSpinBoxEditingFinished ())); + connect (ui.peerLimitSpin, SIGNAL (editingFinished ()), SLOT (onSpinBoxEditingFinished ())); } /*** **** ***/ -QWidget * -Details::createTrackerTab () +void +Details::initTrackerTab () { - QCheckBox * c; - QPushButton * p; - QWidget * top = new QWidget; - QVBoxLayout * v = new QVBoxLayout (top); - QHBoxLayout * h = new QHBoxLayout (); - QVBoxLayout * v2 = new QVBoxLayout (); + myTrackerModel = new TrackerModel (); + myTrackerFilter = new TrackerModelFilter (); + myTrackerFilter->setSourceModel (myTrackerModel); + myTrackerDelegate = new TrackerDelegate (); - v->setSpacing (HIG::PAD_BIG); - v->setContentsMargins (HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG); + ui.trackersView->setModel (myTrackerFilter); + ui.trackersView->setItemDelegate (myTrackerDelegate); - h->setSpacing (HIG::PAD); - h->setContentsMargins (HIG::PAD_SMALL, HIG::PAD_SMALL, HIG::PAD_SMALL, HIG::PAD_SMALL); + ui.addTrackerButton->setIcon (getStockIcon ("list-add", QStyle::SP_DialogOpenButton)); + ui.editTrackerButton->setIcon (getStockIcon ("document-properties", QStyle::SP_DesktopIcon)); + ui.removeTrackerButton->setIcon (getStockIcon ("list-remove", QStyle::SP_TrashIcon)); - v2->setSpacing (HIG::PAD); + ui.showTrackerScrapesCheck->setChecked (myPrefs.getBool (Prefs::SHOW_TRACKER_SCRAPES)); + ui.showBackupTrackersCheck->setChecked (myPrefs.getBool (Prefs::SHOW_BACKUP_TRACKERS)); - myTrackerModel = new TrackerModel; - myTrackerFilter = new TrackerModelFilter; - myTrackerFilter->setSourceModel (myTrackerModel); - myTrackerView = new QTreeView; - myTrackerView->setModel (myTrackerFilter); - myTrackerView->setHeaderHidden (true); - myTrackerView->setSelectionMode (QTreeWidget::ExtendedSelection); - myTrackerView->setRootIsDecorated (false); - myTrackerView->setIndentation (2); - myTrackerView->setItemsExpandable (false); - myTrackerView->setAlternatingRowColors (true); - myTrackerView->setItemDelegate (myTrackerDelegate = new TrackerDelegate ()); - connect (myTrackerView->selectionModel (), SIGNAL (selectionChanged (QItemSelection, QItemSelection)), this, SLOT (onTrackerSelectionChanged ())); - h->addWidget (myTrackerView, 1); - - p = new QPushButton (); - p->setIcon (getStockIcon ("list-add", QStyle::SP_DialogOpenButton)); - p->setToolTip (tr ("Add Tracker")); - myAddTrackerButton = p; - v2->addWidget (p, 1); - connect (p, SIGNAL (clicked (bool)), this, SLOT (onAddTrackerClicked ())); - - p = new QPushButton (); - p->setIcon (getStockIcon ("document-properties", QStyle::SP_DesktopIcon)); - p->setToolTip (tr ("Edit Tracker")); - myAddTrackerButton = p; - p->setEnabled (false); - myEditTrackerButton = p; - v2->addWidget (p, 1); - connect (p, SIGNAL (clicked (bool)), this, SLOT (onEditTrackerClicked ())); - - p = new QPushButton (); - p->setIcon (getStockIcon ("list-remove", QStyle::SP_TrashIcon)); - p->setToolTip (tr ("Remove Trackers")); - p->setEnabled (false); - myRemoveTrackerButton = p; - v2->addWidget (p, 1); - connect (p, SIGNAL (clicked (bool)), this, SLOT (onRemoveTrackerClicked ())); - - v2->addStretch (1); - - h->addLayout (v2, 1); - h->setStretch (1, 0); - - v->addLayout (h, 1); - - c = new QCheckBox (tr ("Show &more details")); - c->setChecked (myPrefs.getBool (Prefs::SHOW_TRACKER_SCRAPES)); - myShowTrackerScrapesCheck = c; - v->addWidget (c, 1); - connect (c, SIGNAL (clicked (bool)), this, SLOT (onShowTrackerScrapesToggled (bool))); - - c = new QCheckBox (tr ("Show &backup trackers")); - c->setChecked (myPrefs.getBool (Prefs::SHOW_BACKUP_TRACKERS)); - myShowBackupTrackersCheck = c; - v->addWidget (c, 1); - connect (c, SIGNAL (clicked (bool)), this, SLOT (onShowBackupTrackersToggled (bool))); - - return top; + connect (ui.trackersView->selectionModel (), SIGNAL (selectionChanged (QItemSelection, QItemSelection)), + SLOT (onTrackerSelectionChanged ())); + connect (ui.addTrackerButton, SIGNAL (clicked ()), SLOT (onAddTrackerClicked ())); + connect (ui.editTrackerButton, SIGNAL (clicked ()), SLOT (onEditTrackerClicked ())); + connect (ui.removeTrackerButton, SIGNAL (clicked ()), SLOT (onRemoveTrackerClicked ())); + connect (ui.showTrackerScrapesCheck, SIGNAL (clicked (bool)), SLOT (onShowTrackerScrapesToggled (bool))); + connect (ui.showBackupTrackersCheck, SIGNAL (clicked (bool)), SLOT (onShowBackupTrackersToggled (bool))); + + onTrackerSelectionChanged (); } /*** **** ***/ -QWidget * -Details::createPeersTab () +void +Details::initPeersTab () { - QWidget * top = new QWidget; - QVBoxLayout * v = new QVBoxLayout (top); - v->setSpacing (HIG::PAD_BIG); - v->setContentsMargins (HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG); - QStringList headers; headers << QString () << tr ("Up") << tr ("Down") << tr ("%") << tr ("Status") << tr ("Address") << tr ("Client"); - myPeerTree = new QTreeWidget; - myPeerTree->setUniformRowHeights (true); - myPeerTree->setHeaderLabels (headers); - myPeerTree->setColumnWidth (0, 20); - myPeerTree->setSortingEnabled (true); - myPeerTree->sortByColumn (COL_ADDRESS, Qt::AscendingOrder); - myPeerTree->setRootIsDecorated (false); - myPeerTree->setTextElideMode (Qt::ElideRight); - v->addWidget (myPeerTree, 1); - - const QFontMetrics m (font ()); - QSize size = m.size (0, "1024 MiB/s"); - myPeerTree->setColumnWidth (COL_UP, size.width ()); - myPeerTree->setColumnWidth (COL_DOWN, size.width ()); - size = m.size (0, " 100% "); - myPeerTree->setColumnWidth (COL_PERCENT, size.width ()); - size = m.size (0, "ODUK?EXI"); - myPeerTree->setColumnWidth (COL_STATUS, size.width ()); - size = m.size (0, "888.888.888.888"); - myPeerTree->setColumnWidth (COL_ADDRESS, size.width ()); - size = m.size (0, "Some BitTorrent Client"); - myPeerTree->setColumnWidth (COL_CLIENT, size.width ()); - myPeerTree->setAlternatingRowColors (true); - - return top; + + ui.peersView->setHeaderLabels (headers); + ui.peersView->sortByColumn (COL_ADDRESS, Qt::AscendingOrder); + + ui.peersView->setColumnWidth (COL_LOCK, 20); + ui.peersView->setColumnWidth (COL_UP, measureViewItem (ui.peersView, "1024 MiB/s")); + ui.peersView->setColumnWidth (COL_DOWN, measureViewItem (ui.peersView, "1024 MiB/s")); + ui.peersView->setColumnWidth (COL_PERCENT, measureViewItem (ui.peersView, "100%")); + ui.peersView->setColumnWidth (COL_STATUS, measureViewItem (ui.peersView, "ODUK?EXI")); + ui.peersView->setColumnWidth (COL_ADDRESS, measureViewItem (ui.peersView, "888.888.888.888")); } /*** **** ***/ -QWidget * -Details::createFilesTab () +void +Details::initFilesTab () { - myFileTreeView = new FileTreeView (); - - connect (myFileTreeView, SIGNAL ( priorityChanged (QSet, int)), - this, SLOT ( onFilePriorityChanged (QSet, int))); - - connect (myFileTreeView, SIGNAL ( wantedChanged (QSet, bool)), - this, SLOT ( onFileWantedChanged (QSet, bool))); - - connect (myFileTreeView, SIGNAL (pathEdited (QString, QString)), - this, SLOT (onPathEdited (QString, QString))); - - connect (myFileTreeView, SIGNAL (openRequested (QString)), - this, SLOT (onOpenRequested (QString))); - - return myFileTreeView; + connect (ui.filesView, SIGNAL (priorityChanged (QSet, int)), SLOT (onFilePriorityChanged (QSet, int))); + connect (ui.filesView, SIGNAL (wantedChanged (QSet, bool)), SLOT (onFileWantedChanged (QSet, bool))); + connect (ui.filesView, SIGNAL (pathEdited (QString, QString)), SLOT (onPathEdited (QString, QString))); + connect (ui.filesView, SIGNAL (openRequested (QString)), SLOT (onOpenRequested (QString))); } void diff --git a/qt/details.h b/qt/details.h index 617801c95..cc91ff191 100644 --- a/qt/details.h +++ b/qt/details.h @@ -15,20 +15,11 @@ #include #include #include -#include #include "prefs.h" -class FileTreeView; -class QTreeView; -class QComboBox; -class QCheckBox; -class QDoubleSpinBox; -class QLabel; -class QRadioButton; -class QSpinBox; -class QTextBrowser; -class QTreeWidget; +#include "ui_details.h" + class QTreeWidgetItem; class Session; class Torrent; @@ -55,17 +46,16 @@ class Details: public QDialog virtual QSize sizeHint () const { return QSize (440, 460); } private: - QWidget * createPeersTab (); - QWidget * createTrackerTab (); - QWidget * createInfoTab (); - QWidget * createFilesTab (); - QWidget * createOptionsTab (); + void initPeersTab (); + void initTrackerTab (); + void initInfoTab (); + void initFilesTab (); + void initOptionsTab (); private: QIcon getStockIcon (const QString& freedesktop_name, int fallback); QString timeToStringRounded (int seconds); QString trimToDesiredWidth (const QString& str); - void enableWhenChecked (QCheckBox *, QWidget *); private: Session& mySession; @@ -76,63 +66,14 @@ class Details: public QDialog bool myChangedTorrents; bool myHavePendingRefresh; - QLabel * myStateLabel; - QLabel * myHaveLabel; - QLabel * myAvailabilityLabel; - QLabel * myDownloadedLabel; - QLabel * myUploadedLabel; - QLabel * myErrorLabel; - QLabel * myRunTimeLabel; - QLabel * myETALabel; - QLabel * myLastActivityLabel; - - QCheckBox * mySessionLimitCheck; - QCheckBox * mySingleDownCheck; - QCheckBox * mySingleUpCheck; - QCheckBox * myShowTrackerScrapesCheck; - QCheckBox * myShowBackupTrackersCheck; - QPushButton * myAddTrackerButton; - QPushButton * myEditTrackerButton; - QPushButton * myRemoveTrackerButton; - QSpinBox * mySingleDownSpin; - QSpinBox * mySingleUpSpin; - QComboBox * myRatioCombo; - QDoubleSpinBox * myRatioSpin; - QComboBox * myIdleCombo; - QSpinBox * myIdleSpin; - QSpinBox * myPeerLimitSpin; - QComboBox * myBandwidthPriorityCombo; - - QLabel * mySizeLabel; - QLabel * myHashLabel; - QLabel * myPrivacyLabel; - QLabel * myOriginLabel; - QLabel * myLocationLabel; - QTextBrowser * myCommentBrowser; - - QLabel * myTrackerLabel; - QLabel * myScrapeTimePrevLabel; - QLabel * myScrapeTimeNextLabel; - QLabel * myScrapeResponseLabel; - QLabel * myAnnounceTimePrevLabel; - QLabel * myAnnounceTimeNextLabel; - QLabel * myAnnounceResponseLabel; - QLabel * myAnnounceManualLabel; + Ui::DetailsDialog ui; TrackerModel * myTrackerModel; TrackerModelFilter * myTrackerFilter; TrackerDelegate * myTrackerDelegate; - QTreeView * myTrackerView; - //QMap myTrackerTiers; - //QMap myTrackerItems; - QTreeWidget * myPeerTree; QMap myPeers; - QWidgetList myWidgets; - - FileTreeView * myFileTreeView; - private slots: void refreshPref (int key); void onBandwidthPriorityChanged (int); diff --git a/qt/details.ui b/qt/details.ui new file mode 100644 index 000000000..23a2c943c --- /dev/null +++ b/qt/details.ui @@ -0,0 +1,936 @@ + + + DetailsDialog + + + + 0 + 0 + 505 + 579 + + + + Torrent Properties + + + [tr-style~="form-section"] +{ + font-weight: bold; + margin-top: 12px; + margin-bottom: 1px; +} +[tr-style~="form-section"][tr-style~="first"] +{ + margin-top: 0; +} +[tr-style~="form-label"] +{ + margin-left: 18px; +} + + + + + + 0 + + + + Information + + + + + + Activity + + + form-section first + + + + + + + Have: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::NoTextInteraction + + + + + + + Availability: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::NoTextInteraction + + + + + + + Uploaded: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::NoTextInteraction + + + + + + + Downloaded: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::NoTextInteraction + + + + + + + State: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::NoTextInteraction + + + + + + + Running time: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::NoTextInteraction + + + + + + + Remaining time: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::NoTextInteraction + + + + + + + Last activity: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::NoTextInteraction + + + + + + + Error: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Details + + + form-section + + + + + + + Size: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::NoTextInteraction + + + + + + + Location: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Hash: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Privacy: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::NoTextInteraction + + + + + + + Origin: + + + form-label + + + + + + + + 0 + 0 + + + + ... + + + Qt::PlainText + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Comment: + + + commentBrowser + + + form-label + + + + + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + Peers + + + + + + true + + + false + + + true + + + true + + + 0 + + + true + + + + + + + + Tracker + + + + + + true + + + QAbstractItemView::ExtendedSelection + + + + + + + Add Tracker + + + Qt::ToolButtonIconOnly + + + + + + + Edit Tracker + + + Qt::ToolButtonIconOnly + + + + + + + Remove Trackers + + + Qt::ToolButtonIconOnly + + + + + + + Qt::Vertical + + + + 1 + 1 + + + + + + + + Show &more details + + + + + + + Show &backup trackers + + + + + + + + Files + + + + + + + + + + Options + + + + + + Speed + + + form-section first + + + + + + + Honor global &limits + + + form-label + + + + + + + Limit &download speed (%1): + + + form-label + + + + + + + false + + + 999999999 + + + 5 + + + + + + + Limit &upload speed (%1): + + + form-label + + + + + + + false + + + 999999999 + + + 5 + + + + + + + Torrent &priority: + + + bandwidthPriorityCombo + + + form-label + + + + + + + + + + Seeding Limits + + + form-section + + + + + + + &Ratio: + + + ratioCombo + + + form-label + + + + + + + + + + + + 0.500000000000000 + + + 999999999.000000000000000 + + + + + + + + + &Idle: + + + idleCombo + + + form-label + + + + + + + + + + + + 1 + + + 9999 + + + 5 + + + + + + + + + Peer Connections + + + form-section + + + + + + + &Maximum peers: + + + peerLimitSpin + + + form-label + + + + + + + 1 + + + 300 + + + 5 + + + + + + + Qt::Vertical + + + + 1 + 1 + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + SqueezeLabel + QLabel +
squeezelabel.h
+
+ + FileTreeView + QTreeView +
file-tree.h
+
+
+ + tabs + errorValueLabel + locationValueLabel + hashValueLabel + originValueLabel + commentBrowser + peersView + trackersView + addTrackerButton + editTrackerButton + removeTrackerButton + showTrackerScrapesCheck + showBackupTrackersCheck + filesView + sessionLimitCheck + singleDownCheck + singleDownSpin + singleUpCheck + singleUpSpin + bandwidthPriorityCombo + ratioCombo + ratioSpin + idleCombo + idleSpin + peerLimitSpin + dialogButtons + + + + + dialogButtons + accepted() + DetailsDialog + accept() + + + 26 + 563 + + + 20 + 20 + + + + + dialogButtons + rejected() + DetailsDialog + reject() + + + 26 + 563 + + + 20 + 20 + + + + + singleDownCheck + toggled(bool) + singleDownSpin + setEnabled(bool) + + + 35 + 99 + + + 247 + 93 + + + + + singleUpCheck + toggled(bool) + singleUpSpin + setEnabled(bool) + + + 35 + 131 + + + 247 + 125 + + + + +
diff --git a/qt/qtr.pro b/qt/qtr.pro index f18307d49..66134e04b 100644 --- a/qt/qtr.pro +++ b/qt/qtr.pro @@ -46,7 +46,8 @@ TRANSLATIONS += translations/transmission_en.ts \ translations/transmission_ru.ts \ translations/transmission_uk.ts -FORMS += mainwin.ui +FORMS += details.ui \ + mainwin.ui RESOURCES += application.qrc SOURCES += about.cc \ add-data.cc \ diff --git a/qt/squeezelabel.cc b/qt/squeezelabel.cc index 4fa77270a..06f246dcf 100644 --- a/qt/squeezelabel.cc +++ b/qt/squeezelabel.cc @@ -40,40 +40,33 @@ ****************************************************************************/ #include -#include #include #include #include "squeezelabel.h" -void -SqueezeLabel::init () -{ - setTextInteractionFlags(Qt::TextSelectableByMouse); -} - SqueezeLabel::SqueezeLabel (const QString& text, QWidget * parent): QLabel (text, parent) { - init(); } SqueezeLabel::SqueezeLabel (QWidget * parent): QLabel (parent) { - init(); } void SqueezeLabel::paintEvent (QPaintEvent * paintEvent) { - Q_UNUSED (paintEvent); + if (hasFocus () && (textInteractionFlags () & (Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse))) + return QLabel::paintEvent (paintEvent); QPainter painter (this); QFontMetrics fm = fontMetrics (); QStyleOption opt; opt.initFrom (this); - const QString elidedText = fm.elidedText (text(), Qt::ElideMiddle, width()); + const QString fullText = text (); + const QString elidedText = fm.elidedText (fullText, Qt::ElideRight, width()); style()->drawItemText (&painter, contentsRect(), alignment(), @@ -81,4 +74,8 @@ SqueezeLabel::paintEvent (QPaintEvent * paintEvent) isEnabled(), elidedText, foregroundRole()); + +#ifndef QT_NO_TOOLTIP + setToolTip (fullText != elidedText ? fullText : QString ()); +#endif } diff --git a/qt/squeezelabel.h b/qt/squeezelabel.h index 2ef8cdaf2..c73ec6edf 100644 --- a/qt/squeezelabel.h +++ b/qt/squeezelabel.h @@ -53,7 +53,6 @@ class SqueezeLabel : public QLabel SqueezeLabel (const QString& text, QWidget *parent=0); protected: - void init (); void paintEvent (QPaintEvent* paintEvent); }; -- 2.40.0