/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/transmission.h>
#include <libtransmission/version.h>
-#include "about.h"
-#include "license.h"
+#include "AboutDialog.h"
+#include "LicenseDialog.h"
AboutDialog::AboutDialog (QWidget * parent):
QDialog (parent, Qt::Dialog),
/*
- * This file Copyright (C) 2010-2014 Mnemosyne LLC
+ * This file Copyright (C) 2010-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef ABOUT_DIALOG_H
-#define ABOUT_DIALOG_H
+#ifndef QTR_ABOUT_DIALOG_H
+#define QTR_ABOUT_DIALOG_H
#include <QDialog>
-#include "ui_about.h"
+#include "ui_AboutDialog.h"
class AboutDialog: public QDialog
{
Ui::AboutDialog ui;
};
-#endif
+#endif // QTR_ABOUT_DIALOG_H
/*
- * This file Copyright (C) 2012-2014 Mnemosyne LLC
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/transmission.h>
#include <libtransmission/crypto-utils.h> // tr_base64_encode()
-#include "add-data.h"
-#include "utils.h"
+#include "AddData.h"
+#include "Utils.h"
int
AddData::set (const QString& key)
/*
- * This file Copyright (C) 2012-2014 Mnemosyne LLC
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef ADD_DATA_H
-#define ADD_DATA_H
+#ifndef QTR_ADD_DATA_H
+#define QTR_ADD_DATA_H
#include <QByteArray>
#include <QString>
static bool isSupported (const QString& str) { return AddData(str).type != NONE; }
};
-#endif
+#endif // QTR_ADD_DATA_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/utils.h>
#include <libtransmission/version.h>
-#include "add-data.h"
-#include "app.h"
-#include "dbus-adaptor.h"
-#include "formatter.h"
-#include "mainwin.h"
-#include "options.h"
-#include "prefs.h"
-#include "session.h"
-#include "session-dialog.h"
-#include "torrent-model.h"
-#include "watchdir.h"
+#include "AddData.h"
+#include "Application.h"
+#include "DBusAdaptor.h"
+#include "Formatter.h"
+#include "MainWindow.h"
+#include "OptionsDialog.h"
+#include "Prefs.h"
+#include "Session.h"
+#include "SessionDialog.h"
+#include "TorrentModel.h"
+#include "WatchDir.h"
namespace
{
}
}
-MyApp::MyApp (int& argc, char ** argv):
+Application::Application (int& argc, char ** argv):
QApplication (argc, argv),
myPrefs(nullptr),
mySession(nullptr),
mySession = new Session (configDir, *myPrefs);
myModel = new TorrentModel (*myPrefs);
- myWindow = new TrMainWindow (*mySession, *myPrefs, *myModel, minimized);
+ myWindow = new MainWindow (*mySession, *myPrefs, *myModel, minimized);
myWatchDir = new WatchDir (*myModel);
// when the session gets torrent info, update the model
// register as the dbus handler for Transmission
if (bus.isConnected ())
{
- new TrDBusAdaptor (this);
+ new DBusAdaptor (this);
if (!bus.registerService (DBUS_SERVICE))
std::cerr << "couldn't register " << qPrintable (DBUS_SERVICE) << std::endl;
if (!bus.registerObject (DBUS_OBJECT_PATH, this))
}
void
-MyApp::quitLater ()
+Application::quitLater ()
{
QTimer::singleShot (0, this, SLOT (quit ()));
}
/* these functions are for popping up desktop notifications */
void
-MyApp::onTorrentsAdded (const QSet<int>& torrents)
+Application::onTorrentsAdded (const QSet<int>& torrents)
{
if (!myPrefs->getBool (Prefs::SHOW_NOTIFICATION_ON_ADD))
return;
}
void
-MyApp::onTorrentCompleted (int id)
+Application::onTorrentCompleted (int id)
{
Torrent * tor = myModel->getTorrentFromId (id);
}
void
-MyApp::onNewTorrentChanged (int id)
+Application::onNewTorrentChanged (int id)
{
Torrent * tor = myModel->getTorrentFromId (id);
***/
void
-MyApp::consentGiven (int result)
+Application::consentGiven (int result)
{
if (result == QMessageBox::Ok)
myPrefs->set<bool> (Prefs::USER_HAS_GIVEN_INFORMED_CONSENT, true);
quit ();
}
-MyApp::~MyApp ()
+Application::~Application ()
{
if (myPrefs != nullptr && myWindow != nullptr)
{
***/
void
-MyApp::refreshPref (int key)
+Application::refreshPref (int key)
{
switch (key)
{
}
void
-MyApp::maybeUpdateBlocklist ()
+Application::maybeUpdateBlocklist ()
{
if (!myPrefs->getBool (Prefs::BLOCKLIST_UPDATES_ENABLED))
return;
}
void
-MyApp::onSessionSourceChanged ()
+Application::onSessionSourceChanged ()
{
mySession->initTorrents ();
mySession->refreshSessionStats ();
}
void
-MyApp::refreshTorrents ()
+Application::refreshTorrents ()
{
// usually we just poll the torrents that have shown recent activity,
// but we also periodically ask for updates on the others to ensure
***/
void
-MyApp::addTorrent (const QString& key)
+Application::addTorrent (const QString& key)
{
const AddData addme (key);
}
void
-MyApp::addTorrent (const AddData& addme)
+Application::addTorrent (const AddData& addme)
{
if (!myPrefs->getBool (Prefs::OPTIONS_PROMPT))
{
***/
void
-MyApp::raise ()
+Application::raise ()
{
alert (myWindow);
}
bool
-MyApp::notifyApp (const QString& title, const QString& body) const
+Application::notifyApp (const QString& title, const QString& body) const
{
const QString dbusServiceName = QString::fromUtf8 ("org.freedesktop.Notifications");
const QString dbusInterfaceName = QString::fromUtf8 ("org.freedesktop.Notifications");
tr_main (int argc,
char * argv[])
{
- MyApp app (argc, argv);
+ Application app (argc, argv);
return app.exec ();
}
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef QTR_APP_H
-#define QTR_APP_H
+#ifndef QTR_APPLICATION_H
+#define QTR_APPLICATION_H
#include <QApplication>
#include <QSet>
#include <QTimer>
#include <QTranslator>
-#include "favicon.h"
+#include "FaviconCache.h"
class AddData;
class Prefs;
class Session;
class TorrentModel;
-class TrMainWindow;
+class MainWindow;
class WatchDir;
-class MyApp: public QApplication
+class Application: public QApplication
{
Q_OBJECT
public:
- MyApp (int& argc, char ** argv);
- virtual ~MyApp ();
+ Application (int& argc, char ** argv);
+ virtual ~Application ();
public:
void raise ();
bool notifyApp (const QString& title, const QString& body) const;
public:
- Favicons favicons;
+ FaviconCache favicons;
private:
Prefs * myPrefs;
Session * mySession;
TorrentModel * myModel;
- TrMainWindow * myWindow;
+ MainWindow * myWindow;
WatchDir * myWatchDir;
QTimer myModelTimer;
QTimer myStatsTimer;
};
#undef qApp
-#define qApp static_cast<MyApp*> (MyApp::instance ())
+#define qApp static_cast<Application*> (Application::instance ())
-#endif
+#endif // QTR_APPLICATION_H
endif()
set(${PROJECT_NAME}_SOURCES
- about.cc
- add-data.cc
- app.cc
- column-resizer.cc
- dbus-adaptor.cc
- details.cc
- favicon.cc
- file-tree.cc
- filterbar.cc
- filters.cc
- formatter.cc
- freespace-label.cc
- hig.cc
- license.cc
- mainwin.cc
- make-dialog.cc
- options.cc
- path-button.cc
- prefs-dialog.cc
- prefs.cc
- relocate.cc
- rpc-client.cc
- session-dialog.cc
- session.cc
- squeezelabel.cc
- stats-dialog.cc
- torrent-delegate-min.cc
- torrent-delegate.cc
- torrent-filter.cc
- torrent-model.cc
- torrent.cc
- tracker-delegate.cc
- tracker-model-filter.cc
- tracker-model.cc
- tricontoolbutton.cc
- utils.cc
- watchdir.cc
+ AboutDialog.cc
+ AddData.cc
+ Application.cc
+ ColumnResizer.cc
+ DBusAdaptor.cc
+ DetailsDialog.cc
+ FaviconCache.cc
+ FileTreeDelegate.cc
+ FileTreeItem.cc
+ FileTreeModel.cc
+ FileTreeView.cc
+ FilterBar.cc
+ FilterBarComboBox.cc
+ FilterBarComboBoxDelegate.cc
+ FilterBarLineEdit.cc
+ Filters.cc
+ Formatter.cc
+ FreeSpaceLabel.cc
+ IconToolButton.cc
+ LicenseDialog.cc
+ MainWindow.cc
+ MakeDialog.cc
+ OptionsDialog.cc
+ PathButton.cc
+ Prefs.cc
+ PrefsDialog.cc
+ RelocateDialog.cc
+ RpcClient.cc
+ Session.cc
+ SessionDialog.cc
+ SqueezeLabel.cc
+ StatsDialog.cc
+ Torrent.cc
+ TorrentDelegate.cc
+ TorrentDelegateMin.cc
+ TorrentFilter.cc
+ TorrentModel.cc
+ TrackerDelegate.cc
+ TrackerModel.cc
+ TrackerModelFilter.cc
+ Utils.cc
+ WatchDir.cc
)
set(${PROJECT_NAME}_HEADERS
- about.h
- add-data.h
- app.h
- column-resizer.h
- dbus-adaptor.h
- details.h
- favicon.h
- file-tree.h
- filterbar.h
- filters.h
- formatter.h
- freespace-label.h
- hig.h
- license.h
- mainwin.h
- make-dialog.h
- options.h
- path-button.h
- prefs-dialog.h
- prefs.h
- relocate.h
- rpc-client.h
- session-dialog.h
- session.h
- speed.h
- squeezelabel.h
- stats-dialog.h
- torrent-delegate-min.h
- torrent-delegate.h
- torrent-filter.h
- torrent-model.h
- torrent.h
- tracker-delegate.h
- tracker-model-filter.h
- tracker-model.h
- tricontoolbutton.h
- types.h
- utils.h
- watchdir.h
+ AboutDialog.h
+ AddData.h
+ Application.h
+ ColumnResizer.h
+ CustomVariantType.h
+ DBusAdaptor.h
+ DetailsDialog.h
+ FaviconCache.h
+ FileTreeDelegate.h
+ FileTreeItem.h
+ FileTreeModel.h
+ FileTreeView.h
+ FilterBar.h
+ FilterBarComboBox.h
+ FilterBarComboBoxDelegate.h
+ FilterBarLineEdit.h
+ Filters.h
+ Formatter.h
+ FreeSpaceLabel.h
+ IconToolButton.h
+ LicenseDialog.h
+ MainWindow.h
+ MakeDialog.h
+ OptionsDialog.h
+ PathButton.h
+ Prefs.h
+ PrefsDialog.h
+ RelocateDialog.h
+ RpcClient.h
+ Session.h
+ SessionDialog.h
+ Speed.h
+ SqueezeLabel.h
+ StatsDialog.h
+ Torrent.h
+ TorrentDelegate.h
+ TorrentDelegateMin.h
+ TorrentFilter.h
+ TorrentModel.h
+ TrackerDelegate.h
+ TrackerModel.h
+ TrackerModelFilter.h
+ Utils.h
+ WatchDir.h
)
tr_qt_wrap_ui(${PROJECT_NAME}_UI_SOURCES
- about.ui
- details.ui
- mainwin.ui
- make-dialog.ui
- make-progress-dialog.ui
- options.ui
- prefs-dialog.ui
- relocate.ui
- session-dialog.ui
- stats-dialog.ui
+ AboutDialog.ui
+ DetailsDialog.ui
+ MainWindow.ui
+ MakeDialog.ui
+ MakeProgressDialog.ui
+ OptionsDialog.ui
+ PrefsDialog.ui
+ RelocateDialog.ui
+ SessionDialog.ui
+ StatsDialog.ui
)
set(${PROJECT_NAME}_QRC_FILES application.qrc)
#include <QGridLayout>
#include <QTimer>
-#include "column-resizer.h"
+#include "ColumnResizer.h"
namespace
{
QSet<QGridLayout *> myLayouts;
};
-#endif
+#endif // QTR_COLUMN_RESIZER_H
/*
- * This file Copyright (C) 2012-2014 Mnemosyne LLC
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QVariant>
-class TrTypes
+class CustomVariantType
{
public:
};
};
-#endif
+#endif // QTR_TYPES_H
/*
- * This file Copyright (C) 2012-2014 Mnemosyne LLC
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#include "add-data.h"
-#include "app.h"
-#include "dbus-adaptor.h"
+#include "AddData.h"
+#include "Application.h"
+#include "DBusAdaptor.h"
-TrDBusAdaptor::TrDBusAdaptor (MyApp* app):
+DBusAdaptor::DBusAdaptor (Application* app):
QDBusAbstractAdaptor (app),
myApp (app)
{
}
bool
-TrDBusAdaptor::PresentWindow ()
+DBusAdaptor::PresentWindow ()
{
myApp->raise ();
return true;
}
bool
-TrDBusAdaptor::AddMetainfo (const QString& key)
+DBusAdaptor::AddMetainfo (const QString& key)
{
AddData addme (key);
/*
- * This file Copyright (C) 2012-2014 Mnemosyne LLC
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#ifndef QTR_DBUS_ADAPTOR_H
#define QTR_DBUS_ADAPTOR_H
-class MyApp;
-
#include <QDBusAbstractAdaptor>
-class TrDBusAdaptor: public QDBusAbstractAdaptor
+class Application;
+
+class DBusAdaptor: public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO( "D-Bus Interface", "com.transmissionbt.Transmission" )
private:
- MyApp * myApp;
+ Application * myApp;
public:
- TrDBusAdaptor( MyApp* );
- virtual ~TrDBusAdaptor() {}
+ DBusAdaptor( Application* );
+ virtual ~DBusAdaptor() {}
public slots:
bool PresentWindow();
bool AddMetainfo( const QString& );
};
-#endif
+#endif // QTR_DBUS_ADAPTOR_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h> // tr_getRatio ()
-#include "column-resizer.h"
-#include "details.h"
-#include "file-tree.h"
-#include "formatter.h"
-#include "hig.h"
-#include "prefs.h"
-#include "session.h"
-#include "squeezelabel.h"
-#include "torrent.h"
-#include "torrent-model.h"
-#include "tracker-delegate.h"
-#include "tracker-model.h"
-#include "tracker-model-filter.h"
-#include "utils.h"
+#include "ColumnResizer.h"
+#include "DetailsDialog.h"
+#include "Formatter.h"
+#include "Prefs.h"
+#include "Session.h"
+#include "SqueezeLabel.h"
+#include "Torrent.h"
+#include "TorrentModel.h"
+#include "TrackerDelegate.h"
+#include "TrackerModel.h"
+#include "TrackerModelFilter.h"
+#include "Utils.h"
class Prefs;
class Session;
***/
QIcon
-Details::getStockIcon (const QString& freedesktop_name, int fallback)
+DetailsDialog::getStockIcon (const QString& freedesktop_name, int fallback)
{
QIcon icon = QIcon::fromTheme (freedesktop_name);
return icon;
}
-Details::Details (Session & session,
+DetailsDialog::DetailsDialog (Session & session,
Prefs & prefs,
const TorrentModel& model,
QWidget * parent):
myTimer.start (REFRESH_INTERVAL_MSEC);
}
-Details::~Details ()
+DetailsDialog::~DetailsDialog ()
{
myTrackerDelegate->deleteLater ();
myTrackerFilter->deleteLater ();
}
void
-Details::setIds (const QSet<int>& ids)
+DetailsDialog::setIds (const QSet<int>& ids)
{
if (ids == myIds)
return;
}
void
-Details::refreshPref (int key)
+DetailsDialog::refreshPref (int key)
{
QString str;
***/
QString
-Details::timeToStringRounded (int seconds)
+DetailsDialog::timeToStringRounded (int seconds)
{
if (seconds > 60)
seconds -= (seconds % 60);
}
void
-Details::onTimer ()
+DetailsDialog::onTimer ()
{
getNewData ();
}
void
-Details::getNewData ()
+DetailsDialog::getNewData ()
{
if (!myIds.empty ())
{
}
void
-Details::onTorrentChanged ()
+DetailsDialog::onTorrentChanged ()
{
if (!myHavePendingRefresh)
{
}
void
-Details::refresh ()
+DetailsDialog::refresh ()
{
const int n = myIds.size ();
const bool single = n == 1;
***/
void
-Details::initInfoTab ()
+DetailsDialog::initInfoTab ()
{
const int h = QFontMetrics (ui.commentBrowser->font ()).lineSpacing () * 4;
ui.commentBrowser->setFixedHeight (h);
***/
void
-Details::onShowTrackerScrapesToggled (bool val)
+DetailsDialog::onShowTrackerScrapesToggled (bool val)
{
myPrefs.set (Prefs::SHOW_TRACKER_SCRAPES, val);
}
void
-Details::onShowBackupTrackersToggled (bool val)
+DetailsDialog::onShowBackupTrackersToggled (bool val)
{
myPrefs.set (Prefs::SHOW_BACKUP_TRACKERS, val);
}
void
-Details::onHonorsSessionLimitsToggled (bool val)
+DetailsDialog::onHonorsSessionLimitsToggled (bool val)
{
mySession.torrentSet (myIds, TR_KEY_honorsSessionLimits, val);
getNewData ();
}
void
-Details::onDownloadLimitedToggled (bool val)
+DetailsDialog::onDownloadLimitedToggled (bool val)
{
mySession.torrentSet (myIds, TR_KEY_downloadLimited, val);
getNewData ();
}
void
-Details::onSpinBoxEditingFinished ()
+DetailsDialog::onSpinBoxEditingFinished ()
{
const QObject * spin = sender ();
const tr_quark key = spin->property (PREF_KEY).toInt ();
}
void
-Details::onUploadLimitedToggled (bool val)
+DetailsDialog::onUploadLimitedToggled (bool val)
{
mySession.torrentSet (myIds, TR_KEY_uploadLimited, val);
getNewData ();
}
void
-Details::onIdleModeChanged (int index)
+DetailsDialog::onIdleModeChanged (int index)
{
const int val = ui.idleCombo->itemData (index).toInt ();
mySession.torrentSet (myIds, TR_KEY_seedIdleMode, val);
}
void
-Details::onIdleLimitChanged ()
+DetailsDialog::onIdleLimitChanged ()
{
//: Spin box suffix, "Stop seeding if idle for: [ 5 minutes ]" (includes leading space after the number, if needed)
const QString unitsSuffix = tr (" minute(s)", 0, ui.idleSpin->value ());
}
void
-Details::onRatioModeChanged (int index)
+DetailsDialog::onRatioModeChanged (int index)
{
const int val = ui.ratioCombo->itemData (index).toInt ();
mySession.torrentSet (myIds, TR_KEY_seedRatioMode, val);
}
void
-Details::onBandwidthPriorityChanged (int index)
+DetailsDialog::onBandwidthPriorityChanged (int index)
{
if (index != -1)
{
}
void
-Details::onTrackerSelectionChanged ()
+DetailsDialog::onTrackerSelectionChanged ()
{
const int selectionCount = ui.trackersView->selectionModel ()->selectedRows ().size ();
ui.editTrackerButton->setEnabled (selectionCount == 1);
}
void
-Details::onAddTrackerClicked ()
+DetailsDialog::onAddTrackerClicked ()
{
bool ok = false;
const QString url = QInputDialog::getText (this,
}
void
-Details::onEditTrackerClicked ()
+DetailsDialog::onEditTrackerClicked ()
{
QItemSelectionModel * selectionModel = ui.trackersView->selectionModel ();
QModelIndexList selectedRows = selectionModel->selectedRows ();
}
void
-Details::onRemoveTrackerClicked ()
+DetailsDialog::onRemoveTrackerClicked ()
{
// make a map of torrentIds to announce URLs to remove
QItemSelectionModel * selectionModel = ui.trackersView->selectionModel ();
}
void
-Details::initOptionsTab ()
+DetailsDialog::initOptionsTab ()
{
const QString speed_K_str = Formatter::unitStr (Formatter::SPEED, Formatter::KB);
***/
void
-Details::initTrackerTab ()
+DetailsDialog::initTrackerTab ()
{
myTrackerModel = new TrackerModel ();
myTrackerFilter = new TrackerModelFilter ();
***/
void
-Details::initPeersTab ()
+DetailsDialog::initPeersTab ()
{
QStringList headers;
headers << QString () << tr ("Up") << tr ("Down") << tr ("%") << tr ("Status") << tr ("Address") << tr ("Client");
***/
void
-Details::initFilesTab ()
+DetailsDialog::initFilesTab ()
{
connect (ui.filesView, SIGNAL (priorityChanged (QSet<int>, int)), SLOT (onFilePriorityChanged (QSet<int>, int)));
connect (ui.filesView, SIGNAL (wantedChanged (QSet<int>, bool)), SLOT (onFileWantedChanged (QSet<int>, bool)));
}
void
-Details::onFilePriorityChanged (const QSet<int>& indices, int priority)
+DetailsDialog::onFilePriorityChanged (const QSet<int>& indices, int priority)
{
tr_quark key;
}
void
-Details::onFileWantedChanged (const QSet<int>& indices, bool wanted)
+DetailsDialog::onFileWantedChanged (const QSet<int>& indices, bool wanted)
{
const tr_quark key = wanted ? TR_KEY_files_wanted : TR_KEY_files_unwanted;
mySession.torrentSet (myIds, key, indices.toList ());
}
void
-Details::onPathEdited (const QString& oldpath, const QString& newname)
+DetailsDialog::onPathEdited (const QString& oldpath, const QString& newname)
{
mySession.torrentRenamePath (myIds, oldpath, newname);
}
void
-Details::onOpenRequested (const QString& path)
+DetailsDialog::onOpenRequested (const QString& path)
{
if (!mySession.isLocal ())
return;
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef DETAILS_DIALOG_H
-#define DETAILS_DIALOG_H
+#ifndef QTR_DETAILS_DIALOG_H
+#define QTR_DETAILS_DIALOG_H
#include <QDialog>
#include <QString>
#include <QSet>
#include <QTimer>
-#include "prefs.h"
+#include "Prefs.h"
-#include "ui_details.h"
+#include "ui_DetailsDialog.h"
class QTreeWidgetItem;
class Session;
class TrackerModel;
class TrackerModelFilter;
-class Details: public QDialog
+class DetailsDialog: public QDialog
{
Q_OBJECT
void onTimer ();
public:
- Details (Session&, Prefs&, const TorrentModel&, QWidget * parent = 0);
- ~Details ();
+ DetailsDialog (Session&, Prefs&, const TorrentModel&, QWidget * parent = 0);
+ ~DetailsDialog ();
void setIds (const QSet<int>& ids);
virtual QSize sizeHint () const { return QSize (440, 460); }
void refresh ();
};
-#endif
+#endif // QTR_DETAILS_DIALOG_H
<customwidget>
<class>SqueezeLabel</class>
<extends>QLabel</extends>
- <header>squeezelabel.h</header>
+ <header>SqueezeLabel.h</header>
</customwidget>
<customwidget>
<class>FileTreeView</class>
<extends>QTreeView</extends>
- <header>file-tree.h</header>
+ <header>FileTreeView.h</header>
</customwidget>
</customwidgets>
<resources/>
/*
- * This file Copyright (C) 2012-2014 Mnemosyne LLC
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QStandardPaths>
#endif
-#include "favicon.h"
+#include "FaviconCache.h"
/***
****
***/
-Favicons::Favicons ()
+FaviconCache::FaviconCache ()
{
myNAM = new QNetworkAccessManager ();
connect (myNAM, SIGNAL(finished(QNetworkReply*)), this, SLOT(onRequestFinished(QNetworkReply*)));
}
-Favicons::~Favicons ()
+FaviconCache::~FaviconCache ()
{
delete myNAM;
}
***/
QString
-Favicons::getCacheDir ()
+FaviconCache::getCacheDir ()
{
const QString base =
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
}
void
-Favicons::ensureCacheDirHasBeenScanned ()
+FaviconCache::ensureCacheDirHasBeenScanned ()
{
static bool hasBeenScanned = false;
}
QString
-Favicons::getHost (const QUrl& url)
+FaviconCache::getHost (const QUrl& url)
{
QString host = url.host ();
const int first_dot = host.indexOf (QLatin1Char ('.'));
}
QSize
-Favicons::getIconSize ()
+FaviconCache::getIconSize ()
{
return QSize (16, 16);
}
QPixmap
-Favicons::find (const QUrl& url)
+FaviconCache::find (const QUrl& url)
{
return findFromHost (getHost (url));
}
QPixmap
-Favicons::findFromHost (const QString& host)
+FaviconCache::findFromHost (const QString& host)
{
ensureCacheDirHasBeenScanned ();
}
void
-Favicons::add (const QUrl& url)
+FaviconCache::add (const QUrl& url)
{
ensureCacheDirHasBeenScanned ();
}
void
-Favicons::onRequestFinished (QNetworkReply * reply)
+FaviconCache::onRequestFinished (QNetworkReply * reply)
{
const QString host = reply->url().host();
/*
- * This file Copyright (C) 2012-2014 Mnemosyne LLC
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef FAVICON_CACHE_H
-#define FAVICON_CACHE_H
-
-class QNetworkAccessManager;
-class QNetworkReply;
-class QUrl;
+#ifndef QTR_FAVICON_CACHE_H
+#define QTR_FAVICON_CACHE_H
#include <QMap>
#include <QString>
#include <QObject>
#include <QPixmap>
-class Favicons: public QObject
+class QNetworkAccessManager;
+class QNetworkReply;
+class QUrl;
+
+class FaviconCache: public QObject
{
Q_OBJECT
public:
- Favicons();
- virtual ~Favicons();
+ FaviconCache();
+ virtual ~FaviconCache();
// returns a cached pixmap, or a NULL pixmap if there's no match in the cache
QPixmap find (const QUrl& url);
void onRequestFinished (QNetworkReply * reply);
};
-#endif
+#endif // QTR_FAVICON_CACHE_H
--- /dev/null
+/*
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#include <QApplication>
+#include <QPainter>
+
+#include "FileTreeDelegate.h"
+#include "FileTreeModel.h"
+
+QSize
+FileTreeDelegate::sizeHint(const QStyleOptionViewItem& item, const QModelIndex& index) const
+{
+ QSize size;
+
+ switch(index.column())
+ {
+ case FileTreeModel::COL_PROGRESS:
+ case FileTreeModel::COL_WANTED:
+ size = QSize(20, 1);
+ break;
+
+ default:
+ size = QItemDelegate::sizeHint (item, index);
+ }
+
+ size.rheight() += 8; // make the spacing a little nicer
+ return size;
+}
+
+void
+FileTreeDelegate::paint (QPainter * painter,
+ const QStyleOptionViewItem & option,
+ const QModelIndex & index) const
+{
+ const int column(index.column());
+
+ if ((column != FileTreeModel::COL_PROGRESS) && (column != FileTreeModel::COL_WANTED))
+ {
+ QItemDelegate::paint(painter, option, index);
+ return;
+ }
+
+ QStyle * style (qApp->style ());
+
+ painter->save();
+ QItemDelegate::drawBackground (painter, option, index);
+
+ if(column == FileTreeModel::COL_PROGRESS)
+ {
+ QStyleOptionProgressBar p;
+ p.state = option.state | QStyle::State_Small;
+ p.direction = qApp->layoutDirection();
+ p.rect = option.rect;
+ p.rect.setSize (QSize(option.rect.width()-2, option.rect.height()-8));
+ p.rect.moveCenter (option.rect.center());
+ p.fontMetrics = qApp->fontMetrics();
+ p.minimum = 0;
+ p.maximum = 100;
+ p.textAlignment = Qt::AlignCenter;
+ p.textVisible = true;
+ p.progress = (int)(100.0*index.data().toDouble());
+ p.text = QString::fromLatin1 ("%1%").arg (p.progress);
+ style->drawControl(QStyle::CE_ProgressBar, &p, painter);
+ }
+ else if(column == FileTreeModel::COL_WANTED)
+ {
+ QStyleOptionButton o;
+ o.state = option.state;
+ o.direction = qApp->layoutDirection();
+ o.rect.setSize (QSize(20, option.rect.height()));
+ o.rect.moveCenter (option.rect.center());
+ o.fontMetrics = qApp->fontMetrics();
+ switch (index.data().toInt())
+ {
+ case Qt::Unchecked: o.state |= QStyle::State_Off; break;
+ case Qt::Checked: o.state |= QStyle::State_On; break;
+ default: o.state |= QStyle::State_NoChange;break;
+ }
+ style->drawControl (QStyle::CE_CheckBox, &o, painter);
+ }
+
+ QItemDelegate::drawFocus (painter, option, option.rect);
+ painter->restore();
+}
--- /dev/null
+/*
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#ifndef QTR_FILE_TREE_DELEGATE_H
+#define QTR_FILE_TREE_DELEGATE_H
+
+#include <QItemDelegate>
+
+class FileTreeDelegate: public QItemDelegate
+{
+ Q_OBJECT
+
+ public:
+ FileTreeDelegate (QObject * parent=0): QItemDelegate(parent) {}
+ virtual ~FileTreeDelegate() {}
+
+ public:
+ virtual QSize sizeHint (const QStyleOptionViewItem&, const QModelIndex&) const;
+ virtual void paint (QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const;
+};
+
+#endif // QTR_FILE_TREE_DELEGATE_H
--- /dev/null
+/*
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#include <algorithm>
+#include <cassert>
+
+#include <QApplication>
+#include <QStyle>
+
+#include <libtransmission/transmission.h> // priorities
+
+#include "FileTreeItem.h"
+#include "FileTreeModel.h"
+#include "Formatter.h"
+#include "Utils.h" // mime icons
+
+const QHash<QString,int>&
+FileTreeItem::getMyChildRows ()
+{
+ const size_t n = childCount();
+
+ // ensure that all the rows are hashed
+ while (myFirstUnhashedRow < n)
+ {
+ myChildRows.insert (myChildren[myFirstUnhashedRow]->name(),
+ myFirstUnhashedRow);
+ ++myFirstUnhashedRow;
+ }
+
+ return myChildRows;
+}
+
+
+FileTreeItem::~FileTreeItem ()
+{
+ assert(myChildren.isEmpty());
+
+ if (myParent != 0)
+ {
+ const int pos = row();
+ assert ((pos>=0) && "couldn't find child in parent's lookup");
+ myParent->myChildren.removeAt(pos);
+ myParent->myChildRows.remove(name());
+ myParent->myFirstUnhashedRow = pos;
+ }
+}
+
+void
+FileTreeItem::appendChild (FileTreeItem * child)
+{
+ const size_t n = childCount();
+ child->myParent = this;
+ myChildren.append (child);
+ myFirstUnhashedRow = n;
+}
+
+FileTreeItem *
+FileTreeItem::child (const QString& filename)
+{
+ FileTreeItem * item(0);
+
+ const int row = getMyChildRows().value (filename, -1);
+ if (row != -1)
+ {
+ item = child (row);
+ assert (filename == item->name());
+ }
+
+ return item;
+}
+
+int
+FileTreeItem::row () const
+{
+ int i(-1);
+
+ if(myParent)
+ {
+ i = myParent->getMyChildRows().value (name(), -1);
+ assert (this == myParent->myChildren[i]);
+ }
+
+ return i;
+}
+
+QVariant
+FileTreeItem::data (int column, int role) const
+{
+ QVariant value;
+
+ if (column == FileTreeModel::COL_FILE_INDEX)
+ {
+ value.setValue (myFileIndex);
+ }
+ else if (role == Qt::EditRole)
+ {
+ if (column == 0)
+ value.setValue (name());
+ }
+ else if ((role == Qt::TextAlignmentRole) && column == FileTreeModel::COL_SIZE)
+ {
+ value = Qt::AlignRight + Qt::AlignVCenter;
+ }
+ else if (role == Qt::DisplayRole)
+ {
+ switch(column)
+ {
+ case FileTreeModel::COL_NAME:
+ value.setValue (name());
+ break;
+
+ case FileTreeModel::COL_SIZE:
+ value.setValue (sizeString() + QLatin1String (" "));
+ break;
+
+ case FileTreeModel::COL_PROGRESS:
+ value.setValue (progress());
+ break;
+
+ case FileTreeModel::COL_WANTED:
+ value.setValue (isSubtreeWanted());
+ break;
+
+ case FileTreeModel::COL_PRIORITY:
+ value.setValue (priorityString());
+ break;
+ }
+ }
+ else if (role == Qt::DecorationRole && column == FileTreeModel::COL_NAME)
+ {
+ if (childCount () > 0)
+ value = qApp->style ()->standardIcon (QStyle::SP_DirOpenIcon);
+ else
+ value = Utils::guessMimeIcon (name ());
+ }
+
+ return value;
+}
+
+void
+FileTreeItem::getSubtreeWantedSize (uint64_t& have, uint64_t& total) const
+{
+ if (myIsWanted)
+ {
+ have += myHaveSize;
+ total += myTotalSize;
+ }
+
+ for (const FileTreeItem * const i: myChildren)
+ i->getSubtreeWantedSize(have, total);
+}
+
+double
+FileTreeItem::progress () const
+{
+ double d(0);
+ uint64_t have(0), total(0);
+
+ getSubtreeWantedSize (have, total);
+ if (total)
+ d = have / (double)total;
+
+ return d;
+}
+
+QString
+FileTreeItem::sizeString () const
+{
+ QString str;
+
+ if (myChildren.isEmpty())
+ {
+ str = Formatter::sizeToString (myTotalSize);
+ }
+ else
+ {
+ uint64_t have = 0;
+ uint64_t total = 0;
+ getSubtreeWantedSize (have, total);
+ str = Formatter::sizeToString (total);
+ }
+
+ return str;
+}
+
+std::pair<int,int>
+FileTreeItem::update (const QString& name,
+ bool wanted,
+ int priority,
+ uint64_t haveSize,
+ bool updateFields)
+{
+ int changed_count = 0;
+ int changed_columns[4];
+
+ if (myName != name)
+ {
+ if (myParent)
+ myParent->myFirstUnhashedRow = row();
+
+ myName = name;
+ changed_columns[changed_count++] = FileTreeModel::COL_NAME;
+ }
+
+ if (fileIndex () != -1)
+ {
+ if (myHaveSize != haveSize)
+ {
+ myHaveSize = haveSize;
+ changed_columns[changed_count++] = FileTreeModel::COL_PROGRESS;
+ }
+
+ if (updateFields)
+ {
+ if (myIsWanted != wanted)
+ {
+ myIsWanted = wanted;
+ changed_columns[changed_count++] = FileTreeModel::COL_WANTED;
+ }
+
+ if (myPriority != priority)
+ {
+ myPriority = priority;
+ changed_columns[changed_count++] = FileTreeModel::COL_PRIORITY;
+ }
+ }
+ }
+
+ std::pair<int,int> changed (-1, -1);
+ if (changed_count > 0)
+ {
+ std::sort (changed_columns, changed_columns+changed_count);
+ changed.first = changed_columns[0];
+ changed.second = changed_columns[changed_count-1];
+ }
+ return changed;
+}
+
+QString
+FileTreeItem::priorityString () const
+{
+ const int i = priority();
+
+ switch (i)
+ {
+ case LOW: return tr("Low");
+ case HIGH: return tr("High");
+ case NORMAL: return tr("Normal");
+ default: return tr("Mixed");
+ }
+}
+
+int
+FileTreeItem::priority () const
+{
+ int i(0);
+
+ if (myChildren.isEmpty())
+ {
+ switch (myPriority)
+ {
+ case TR_PRI_LOW:
+ i |= LOW;
+ break;
+
+ case TR_PRI_HIGH:
+ i |= HIGH;
+ break;
+
+ default:
+ i |= NORMAL;
+ break;
+ }
+ }
+
+ for (const FileTreeItem * const child: myChildren)
+ i |= child->priority();
+
+ return i;
+}
+
+void
+FileTreeItem::setSubtreePriority (int i, QSet<int>& ids)
+{
+ if (myPriority != i)
+ {
+ myPriority = i;
+
+ if (myFileIndex >= 0)
+ ids.insert (myFileIndex);
+ }
+
+ for (FileTreeItem * const child: myChildren)
+ child->setSubtreePriority (i, ids);
+}
+
+void
+FileTreeItem::twiddlePriority (QSet<int>& ids, int& p)
+{
+ const int old(priority());
+
+ if (old & LOW)
+ p = TR_PRI_NORMAL;
+ else if (old & NORMAL)
+ p = TR_PRI_HIGH;
+ else
+ p = TR_PRI_LOW;
+
+ setSubtreePriority (p, ids);
+}
+
+int
+FileTreeItem::isSubtreeWanted () const
+{
+ if(myChildren.isEmpty())
+ return myIsWanted ? Qt::Checked : Qt::Unchecked;
+
+ int wanted(-1);
+ for (const FileTreeItem * const child: myChildren)
+ {
+ const int childWanted = child->isSubtreeWanted();
+
+ if (wanted == -1)
+ wanted = childWanted;
+
+ if (wanted != childWanted)
+ wanted = Qt::PartiallyChecked;
+
+ if (wanted == Qt::PartiallyChecked)
+ return wanted;
+ }
+
+ return wanted;
+}
+
+void
+FileTreeItem::setSubtreeWanted (bool b, QSet<int>& ids)
+{
+ if (myIsWanted != b)
+ {
+ myIsWanted = b;
+
+ if (myFileIndex >= 0)
+ ids.insert(myFileIndex);
+ }
+
+ for (FileTreeItem * const child: myChildren)
+ child->setSubtreeWanted (b, ids);
+}
+
+void
+FileTreeItem::twiddleWanted (QSet<int>& ids, bool& wanted)
+{
+ wanted = isSubtreeWanted() != Qt::Checked;
+ setSubtreeWanted (wanted, ids);
+}
+
+QString
+FileTreeItem::path () const
+{
+ QString itemPath;
+ const FileTreeItem * item = this;
+
+ while (item != NULL && !item->name().isEmpty())
+ {
+ if (itemPath.isEmpty())
+ itemPath = item->name();
+ else
+ itemPath = item->name() + QLatin1Char ('/') + itemPath;
+ item = item->parent ();
+ }
+
+ return itemPath;
+}
+
+bool
+FileTreeItem::isComplete () const
+{
+ return myHaveSize == totalSize ();
+}
--- /dev/null
+/*
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#ifndef QTR_FILE_TREE_ITEM_H
+#define QTR_FILE_TREE_ITEM_H
+
+#include <stdint.h>
+
+#include <QObject>
+#include <QList>
+#include <QHash>
+#include <QSet>
+#include <QString>
+#include <QVariant>
+
+class FileTreeItem: public QObject
+{
+ Q_OBJECT
+
+ enum { LOW=(1<<0), NORMAL=(1<<1), HIGH=(1<<2) };
+
+ public:
+
+ virtual ~FileTreeItem();
+
+ FileTreeItem (const QString& name=QString (), int fileIndex=-1, uint64_t size=0):
+ myFileIndex (fileIndex),
+ myParent (0),
+ myName (name),
+ myPriority (0),
+ myIsWanted (0),
+ myHaveSize (0),
+ myTotalSize (size),
+ myFirstUnhashedRow (0) {}
+
+ public:
+ void appendChild (FileTreeItem *child);
+ FileTreeItem * child (const QString& filename);
+ FileTreeItem * child (int row) { return myChildren.at(row); }
+ int childCount () const { return myChildren.size(); }
+ FileTreeItem * parent () { return myParent; }
+ const FileTreeItem * parent () const { return myParent; }
+ int row () const;
+ const QString& name () const { return myName; }
+ QVariant data (int column, int role) const;
+ std::pair<int,int> update (const QString& name, bool want, int priority, uint64_t have, bool updateFields);
+ void twiddleWanted (QSet<int>& fileIds, bool&);
+ void twiddlePriority (QSet<int>& fileIds, int&);
+ int fileIndex () const { return myFileIndex; }
+ uint64_t totalSize () const { return myTotalSize; }
+ QString path () const;
+ bool isComplete () const;
+
+ private:
+ void setSubtreePriority (int priority, QSet<int>& fileIds);
+ void setSubtreeWanted (bool, QSet<int>& fileIds);
+ QString priorityString () const;
+ QString sizeString () const;
+ void getSubtreeWantedSize (uint64_t& have, uint64_t& total) const;
+ double progress () const;
+ int priority () const;
+ int isSubtreeWanted () const;
+
+ const int myFileIndex;
+ FileTreeItem * myParent;
+ QList<FileTreeItem*> myChildren;
+ QHash<QString,int> myChildRows;
+ const QHash<QString,int>& getMyChildRows();
+ QString myName;
+ int myPriority;
+ bool myIsWanted;
+ uint64_t myHaveSize;
+ const uint64_t myTotalSize;
+ size_t myFirstUnhashedRow;
+};
+
+#endif // QTR_FILE_TREE_ITEM_H
--- /dev/null
+/*
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#include <cassert>
+
+#include <QStringList>
+
+#include "FileTreeItem.h"
+#include "FileTreeModel.h"
+
+FileTreeModel::FileTreeModel (QObject * parent, bool isEditable):
+ QAbstractItemModel(parent),
+ myRootItem (new FileTreeItem),
+ myIndexCache (),
+ myIsEditable (isEditable)
+{
+}
+
+FileTreeModel::~FileTreeModel()
+{
+ clear();
+
+ delete myRootItem;
+}
+
+void
+FileTreeModel::setEditable (bool editable)
+{
+ myIsEditable = editable;
+}
+
+FileTreeItem *
+FileTreeModel::itemFromIndex (const QModelIndex& index) const
+{
+ return static_cast<FileTreeItem*>(index.internalPointer());
+}
+
+QVariant
+FileTreeModel::data (const QModelIndex &index, int role) const
+{
+ QVariant value;
+
+ if (index.isValid())
+ value = itemFromIndex(index)->data (index.column(), role);
+
+ return value;
+}
+
+Qt::ItemFlags
+FileTreeModel::flags (const QModelIndex& index) const
+{
+ int i(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+
+ if(myIsEditable && (index.column() == COL_NAME))
+ i |= Qt::ItemIsEditable;
+
+ if(index.column() == COL_WANTED)
+ i |= Qt::ItemIsUserCheckable | Qt::ItemIsTristate;
+
+ return (Qt::ItemFlags)i;
+}
+
+bool
+FileTreeModel::setData (const QModelIndex& index, const QVariant& newname, int role)
+{
+ if (role == Qt::EditRole)
+ {
+ FileTreeItem * item = itemFromIndex (index);
+
+ emit pathEdited (item->path (), newname.toString ());
+ }
+
+ return false; // don't update the view until the session confirms the change
+}
+
+QVariant
+FileTreeModel::headerData (int column, Qt::Orientation orientation, int role) const
+{
+ QVariant data;
+
+ if (orientation==Qt::Horizontal && role==Qt::DisplayRole)
+ {
+ switch (column)
+ {
+ case COL_NAME:
+ data.setValue (tr("File"));
+ break;
+
+ case COL_SIZE:
+ data.setValue (tr("Size"));
+ break;
+
+ case COL_PROGRESS:
+ data.setValue (tr("Progress"));
+ break;
+
+ case COL_WANTED:
+ data.setValue (tr("Download"));
+ break;
+
+ case COL_PRIORITY:
+ data.setValue (tr("Priority"));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return data;
+}
+
+QModelIndex
+FileTreeModel::index (int row, int column, const QModelIndex& parent) const
+{
+ QModelIndex i;
+
+ if (hasIndex (row, column, parent))
+ {
+ FileTreeItem * parentItem;
+
+ if (!parent.isValid ())
+ parentItem = myRootItem;
+ else
+ parentItem = itemFromIndex (parent);
+
+ FileTreeItem * childItem = parentItem->child (row);
+
+ if (childItem)
+ i = createIndex (row, column, childItem);
+ }
+
+ return i;
+}
+
+QModelIndex
+FileTreeModel::parent (const QModelIndex& child) const
+{
+ return parent (child, 0); // QAbstractItemModel::parent() wants col 0
+}
+
+QModelIndex
+FileTreeModel::parent (const QModelIndex& child, int column) const
+{
+ QModelIndex parent;
+
+ if (child.isValid())
+ parent = indexOf (itemFromIndex(child)->parent(), column);
+
+ return parent;
+}
+
+int
+FileTreeModel::rowCount (const QModelIndex& parent) const
+{
+ FileTreeItem * parentItem;
+
+ if (parent.isValid())
+ parentItem = itemFromIndex (parent);
+ else
+ parentItem = myRootItem;
+
+ return parentItem->childCount();
+}
+
+int
+FileTreeModel::columnCount (const QModelIndex& parent) const
+{
+ Q_UNUSED(parent);
+
+ return NUM_COLUMNS;
+}
+
+QModelIndex
+FileTreeModel::indexOf (FileTreeItem * item, int column) const
+{
+ if (!item || item==myRootItem)
+ return QModelIndex();
+
+ return createIndex(item->row(), column, item);
+}
+
+void
+FileTreeModel::clearSubtree (const QModelIndex& top)
+{
+ size_t i = rowCount (top);
+
+ while (i > 0)
+ clearSubtree(index(--i, 0, top));
+
+ FileTreeItem * const item = itemFromIndex (top);
+ if (item == 0)
+ return;
+
+ if (item->fileIndex () != -1)
+ myIndexCache.remove (item->fileIndex ());
+
+ delete item;
+}
+
+void
+FileTreeModel::clear ()
+{
+ beginResetModel ();
+ clearSubtree (QModelIndex());
+ endResetModel ();
+
+ assert (myIndexCache.isEmpty ());
+}
+
+FileTreeItem *
+FileTreeModel::findItemForFileIndex (int fileIndex) const
+{
+ return myIndexCache.value (fileIndex, 0);
+}
+
+void
+FileTreeModel::addFile (int fileIndex,
+ const QString & filename,
+ bool wanted,
+ int priority,
+ uint64_t totalSize,
+ uint64_t have,
+ QList<QModelIndex> & rowsAdded,
+ bool updateFields)
+{
+ FileTreeItem * item;
+ QStringList tokens = filename.split (QChar::fromLatin1('/'));
+
+ item = findItemForFileIndex (fileIndex);
+
+ if (item) // this file is already in the tree, we've added this
+ {
+ QModelIndex indexWithChangedParents;
+ while (!tokens.isEmpty())
+ {
+ const QString token = tokens.takeLast();
+ const std::pair<int,int> changed = item->update (token, wanted, priority, have, updateFields);
+ if (changed.first >= 0)
+ {
+ dataChanged (indexOf (item, changed.first), indexOf (item, changed.second));
+ if (!indexWithChangedParents.isValid () &&
+ changed.first <= COL_PRIORITY && changed.second >= COL_SIZE)
+ indexWithChangedParents = indexOf (item, 0);
+ }
+ item = item->parent();
+ }
+ assert (item == myRootItem);
+ if (indexWithChangedParents.isValid ())
+ parentsChanged (indexWithChangedParents, COL_SIZE, COL_PRIORITY);
+ }
+ else // we haven't build the FileTreeItems for these tokens yet
+ {
+ bool added = false;
+
+ item = myRootItem;
+ while (!tokens.isEmpty())
+ {
+ const QString token = tokens.takeFirst();
+ FileTreeItem * child(item->child(token));
+ if (!child)
+ {
+ added = true;
+ QModelIndex parentIndex (indexOf(item, 0));
+ const int n (item->childCount());
+
+ beginInsertRows (parentIndex, n, n);
+ if (tokens.isEmpty())
+ child = new FileTreeItem (token, fileIndex, totalSize);
+ else
+ child = new FileTreeItem (token);
+ item->appendChild (child);
+ endInsertRows ();
+
+ rowsAdded.append (indexOf(child, 0));
+ }
+ item = child;
+ }
+
+ if (item != myRootItem)
+ {
+ assert (item->fileIndex() == fileIndex);
+ assert (item->totalSize() == totalSize);
+
+ myIndexCache[fileIndex] = item;
+
+ const std::pair<int,int> changed = item->update (item->name(), wanted, priority, have, added || updateFields);
+ if (changed.first >= 0)
+ dataChanged (indexOf (item, changed.first), indexOf (item, changed.second));
+ }
+ }
+}
+
+void
+FileTreeModel::parentsChanged (const QModelIndex& index, int firstColumn, int lastColumn)
+{
+ assert (firstColumn <= lastColumn);
+
+ QModelIndex walk = index;
+
+ for (;;)
+ {
+ walk = parent (walk, firstColumn);
+ if (!walk.isValid ())
+ break;
+
+ dataChanged (walk, walk.sibling (walk.row (), lastColumn));
+ }
+}
+
+void
+FileTreeModel::subtreeChanged (const QModelIndex& index, int firstColumn, int lastColumn)
+{
+ assert (firstColumn <= lastColumn);
+
+ const int childCount = rowCount (index);
+ if (!childCount)
+ return;
+
+ // tell everyone that this tier changed
+ dataChanged (index.child (0, firstColumn), index.child (childCount - 1, lastColumn));
+
+ // walk the subtiers
+ for (int i=0; i<childCount; ++i)
+ subtreeChanged (index.child (i, 0), firstColumn, lastColumn);
+}
+
+void
+FileTreeModel::clicked (const QModelIndex& index)
+{
+ const int column (index.column());
+
+ if (!index.isValid())
+ return;
+
+ if (column == COL_WANTED)
+ {
+ bool want;
+ QSet<int> file_ids;
+ FileTreeItem * item;
+
+ item = itemFromIndex (index);
+ item->twiddleWanted (file_ids, want);
+ emit wantedChanged (file_ids, want);
+
+ dataChanged (index, index);
+ parentsChanged (index, COL_SIZE, COL_WANTED);
+ subtreeChanged (index, COL_WANTED, COL_WANTED);
+ }
+ else if (column == COL_PRIORITY)
+ {
+ int priority;
+ QSet<int> file_ids;
+ FileTreeItem * item;
+
+ item = itemFromIndex (index);
+ item->twiddlePriority (file_ids, priority);
+ emit priorityChanged (file_ids, priority);
+
+ dataChanged (index, index);
+ parentsChanged (index, column, column);
+ subtreeChanged (index, column, column);
+ }
+}
+
+void
+FileTreeModel::doubleClicked (const QModelIndex& index)
+{
+ if (!index.isValid())
+ return;
+
+ const int column (index.column());
+ if (column == COL_WANTED || column == COL_PRIORITY)
+ return;
+
+ FileTreeItem * item = itemFromIndex (index);
+
+ if (item->childCount () == 0 && item->isComplete ())
+ emit openRequested (item->path ());
+}
--- /dev/null
+/*
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#ifndef QTR_FILE_TREE_MODEL_H
+#define QTR_FILE_TREE_MODEL_H
+
+#include <stdint.h>
+
+#include <QAbstractItemModel>
+#include <QList>
+#include <QMap>
+#include <QSet>
+
+class FileTreeItem;
+
+class FileTreeModel: public QAbstractItemModel
+{
+ Q_OBJECT
+
+ public:
+ enum
+ {
+ COL_NAME,
+ FIRST_VISIBLE_COLUMN = COL_NAME,
+ COL_SIZE,
+ COL_PROGRESS,
+ COL_WANTED,
+ COL_PRIORITY,
+ LAST_VISIBLE_COLUMN = COL_PRIORITY,
+
+ COL_FILE_INDEX,
+ NUM_COLUMNS
+ };
+
+ public:
+ FileTreeModel (QObject *parent = 0, bool isEditable = true);
+ ~FileTreeModel ();
+
+ void setEditable (bool editable);
+
+ public:
+ QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const;
+ Qt::ItemFlags flags (const QModelIndex& index) const;
+ QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) const;
+ QModelIndex parent (const QModelIndex& child) const;
+ QModelIndex parent (const QModelIndex& child, int column) const;
+ int rowCount (const QModelIndex& parent = QModelIndex()) const;
+ int columnCount (const QModelIndex &parent = QModelIndex()) const;
+ virtual bool setData (const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
+
+ signals:
+ void priorityChanged (const QSet<int>& fileIndices, int);
+ void wantedChanged (const QSet<int>& fileIndices, bool);
+ void pathEdited (const QString& oldpath, const QString& newname);
+ void openRequested (const QString& path);
+
+ public:
+ void clear ();
+ void addFile (int index, const QString& filename,
+ bool wanted, int priority,
+ uint64_t size, uint64_t have,
+ QList<QModelIndex>& rowsAdded,
+ bool torrentChanged);
+
+ private:
+ void clearSubtree (const QModelIndex &);
+ QModelIndex indexOf (FileTreeItem *, int column) const;
+ void parentsChanged (const QModelIndex &, int firstColumn, int lastColumn);
+ void subtreeChanged (const QModelIndex &, int firstColumn, int lastColumn);
+ FileTreeItem * findItemForFileIndex (int fileIndex) const;
+ FileTreeItem * itemFromIndex (const QModelIndex&) const;
+
+ private:
+ FileTreeItem * myRootItem;
+ QMap<int, FileTreeItem *> myIndexCache;
+ bool myIsEditable;
+
+ public slots:
+ void clicked (const QModelIndex & index);
+ void doubleClicked (const QModelIndex & index);
+};
+
+#endif // QTR_FILE_TREE_MODEL_H
--- /dev/null
+/*
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#include <algorithm>
+
+#include <QHeaderView>
+#include <QResizeEvent>
+#include <QSortFilterProxyModel>
+
+#include "FileTreeDelegate.h"
+#include "FileTreeModel.h"
+#include "FileTreeView.h"
+
+FileTreeView::FileTreeView (QWidget * parent, bool isEditable):
+ QTreeView (parent),
+ myModel (new FileTreeModel (this, isEditable)),
+ myProxy (new QSortFilterProxyModel (this)),
+ myDelegate (new FileTreeDelegate (this))
+{
+ setSortingEnabled (true);
+ setAlternatingRowColors (true);
+ setSelectionBehavior (QAbstractItemView::SelectRows);
+ setSelectionMode (QAbstractItemView::ExtendedSelection);
+ myProxy->setSourceModel (myModel);
+ setModel (myProxy);
+ setItemDelegate (myDelegate);
+ setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
+ sortByColumn (FileTreeModel::COL_NAME, Qt::AscendingOrder);
+ installEventFilter (this);
+
+ for (int i=0; i<FileTreeModel::NUM_COLUMNS; ++i)
+ {
+ setColumnHidden (i, (i<FileTreeModel::FIRST_VISIBLE_COLUMN) || (FileTreeModel::LAST_VISIBLE_COLUMN<i));
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ header()->setResizeMode(i, QHeaderView::Interactive);
+#else
+ header()->setSectionResizeMode(i, QHeaderView::Interactive);
+#endif
+ }
+
+ connect (this, SIGNAL(clicked(QModelIndex)),
+ this, SLOT(onClicked(QModelIndex)));
+
+ connect (this, SIGNAL(doubleClicked(QModelIndex)),
+ this, SLOT(onDoubleClicked(QModelIndex)));
+
+ connect (myModel, SIGNAL(priorityChanged(QSet<int>, int)),
+ this, SIGNAL(priorityChanged(QSet<int>, int)));
+
+ connect (myModel, SIGNAL(wantedChanged(QSet<int>, bool)),
+ this, SIGNAL(wantedChanged(QSet<int>, bool)));
+
+ connect (myModel, SIGNAL(pathEdited(QString, QString)),
+ this, SIGNAL(pathEdited(QString, QString)));
+
+ connect (myModel, SIGNAL (openRequested (QString)),
+ this, SLOT (onOpenRequested (QString)),
+ Qt::QueuedConnection);
+}
+
+void
+FileTreeView::onClicked (const QModelIndex& proxyIndex)
+{
+ const QModelIndex modelIndex = myProxy->mapToSource (proxyIndex);
+ myModel->clicked (modelIndex);
+}
+
+void
+FileTreeView::onDoubleClicked (const QModelIndex& proxyIndex)
+{
+ const QModelIndex modelIndex = myProxy->mapToSource (proxyIndex);
+ myModel->doubleClicked (modelIndex);
+}
+
+void
+FileTreeView::onOpenRequested (const QString& path)
+{
+ if (state () == EditingState)
+ return;
+
+ emit openRequested (path);
+}
+
+bool
+FileTreeView::eventFilter (QObject * o, QEvent * event)
+{
+ // this is kind of a hack to get the last three columns be the
+ // right size, and to have the filename column use whatever
+ // space is left over...
+ if ((o == this) && (event->type() == QEvent::Resize))
+ {
+ QResizeEvent * r = static_cast<QResizeEvent*> (event);
+ int left = r->size().width();
+ const QFontMetrics fontMetrics(font());
+ for (int column=FileTreeModel::FIRST_VISIBLE_COLUMN; column<=FileTreeModel::LAST_VISIBLE_COLUMN; ++column)
+ {
+ if (column == FileTreeModel::COL_NAME)
+ continue;
+ if (isColumnHidden (column))
+ continue;
+
+ QString header;
+ if (column == FileTreeModel::COL_SIZE)
+ header = QLatin1String ("999.9 KiB");
+ else
+ header = myModel->headerData (column, Qt::Horizontal).toString();
+ header += QLatin1String (" ");
+ const int width = fontMetrics.size (0, header).width();
+ setColumnWidth (column, width);
+ left -= width;
+ }
+ left -= 20; // not sure why this is necessary. it works in different themes + font sizes though...
+ setColumnWidth(FileTreeModel::COL_NAME, std::max(left,0));
+ }
+
+ // handle using the keyboard to toggle the
+ // wanted/unwanted state or the file priority
+ else if (event->type () == QEvent::KeyPress && state () != EditingState)
+ {
+ switch (static_cast<QKeyEvent*> (event)->key ())
+ {
+ case Qt::Key_Space:
+ for (const QModelIndex& i: selectionModel ()->selectedRows (FileTreeModel::COL_WANTED))
+ clicked (i);
+ break;
+
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ for (const QModelIndex& i: selectionModel ()->selectedRows (FileTreeModel::COL_PRIORITY))
+ clicked (i);
+ break;
+ }
+ }
+
+ return false;
+}
+
+void
+FileTreeView::update (const FileList& files, bool updateFields)
+{
+ for (const TorrentFile& file: files)
+ {
+ QList<QModelIndex> added;
+ myModel->addFile (file.index, file.filename, file.wanted, file.priority, file.size, file.have, added, updateFields);
+ for (const QModelIndex& i: added)
+ expand (myProxy->mapFromSource(i));
+ }
+}
+
+void
+FileTreeView::clear ()
+{
+ myModel->clear();
+}
+
+void
+FileTreeView::setEditable (bool editable)
+{
+ myModel->setEditable (editable);
+}
--- /dev/null
+/*
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#ifndef QTR_FILE_TREE_VIEW_H
+#define QTR_FILE_TREE_VIEW_H
+
+#include <QSet>
+#include <QTreeView>
+
+#include "Torrent.h" // FileList
+
+class QSortFilterProxyModel;
+
+class FileTreeDelegate;
+class FileTreeModel;
+
+class FileTreeView: public QTreeView
+{
+ Q_OBJECT
+
+ public:
+ FileTreeView (QWidget * parent=0, bool editable=true);
+ void clear ();
+ void update (const FileList& files, bool updateProperties=true);
+
+ void setEditable (bool editable);
+
+ signals:
+ void priorityChanged (const QSet<int>& fileIndices, int priority);
+ void wantedChanged (const QSet<int>& fileIndices, bool wanted);
+ void pathEdited (const QString& oldpath, const QString& newname);
+ void openRequested (const QString& path);
+
+ protected:
+ bool eventFilter (QObject *, QEvent *);
+
+ private:
+ FileTreeModel * myModel;
+ QSortFilterProxyModel * myProxy;
+ FileTreeDelegate * myDelegate;
+
+ public slots:
+ void onClicked (const QModelIndex& index);
+ void onDoubleClicked (const QModelIndex& index);
+ void onOpenRequested (const QString& path);
+};
+
+#endif // QTR_FILE_TREE_VIEW_H
--- /dev/null
+/*
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QStandardItemModel>
+
+#include "Application.h"
+#include "FaviconCache.h"
+#include "Filters.h"
+#include "FilterBar.h"
+#include "FilterBarComboBox.h"
+#include "FilterBarComboBoxDelegate.h"
+#include "FilterBarLineEdit.h"
+#include "Prefs.h"
+#include "TorrentFilter.h"
+#include "TorrentModel.h"
+
+enum
+{
+ ActivityRole = FilterBarComboBox::UserRole,
+ TrackerRole
+};
+
+namespace
+{
+ QString
+ readableHostName (const QString& host)
+ {
+ // get the readable name...
+ QString name = host;
+ const int pos = name.lastIndexOf (QLatin1Char ('.'));
+ if (pos >= 0)
+ name.truncate (pos);
+ if (!name.isEmpty ())
+ name[0] = name[0].toUpper ();
+ return name;
+ }
+}
+
+/***
+****
+***/
+
+FilterBarComboBox *
+FilterBar::createActivityCombo ()
+{
+ FilterBarComboBox * c = new FilterBarComboBox (this);
+ FilterBarComboBoxDelegate * delegate = new FilterBarComboBoxDelegate (this, c);
+ c->setItemDelegate (delegate);
+
+ QStandardItemModel * model = new QStandardItemModel (this);
+
+ QStandardItem * row = new QStandardItem (tr ("All"));
+ row->setData (FilterMode::SHOW_ALL, ActivityRole);
+ model->appendRow (row);
+
+ model->appendRow (new QStandardItem); // separator
+ delegate->setSeparator (model, model->index (1, 0));
+
+ row = new QStandardItem (QIcon::fromTheme (QLatin1String ("system-run")), tr ("Active"));
+ row->setData (FilterMode::SHOW_ACTIVE, ActivityRole);
+ model->appendRow (row);
+
+ row = new QStandardItem (QIcon::fromTheme (QLatin1String ("go-down")), tr ("Downloading"));
+ row->setData (FilterMode::SHOW_DOWNLOADING, ActivityRole);
+ model->appendRow (row);
+
+ row = new QStandardItem (QIcon::fromTheme (QLatin1String ("go-up")), tr ("Seeding"));
+ row->setData (FilterMode::SHOW_SEEDING, ActivityRole);
+ model->appendRow (row);
+
+ row = new QStandardItem (QIcon::fromTheme (QLatin1String ("media-playback-pause")), tr ("Paused"));
+ row->setData (FilterMode::SHOW_PAUSED, ActivityRole);
+ model->appendRow (row);
+
+ row = new QStandardItem (QIcon::fromTheme (QLatin1String ("dialog-ok")), tr ("Finished"));
+ row->setData (FilterMode::SHOW_FINISHED, ActivityRole);
+ model->appendRow (row);
+
+ row = new QStandardItem (QIcon::fromTheme (QLatin1String ("view-refresh")), tr ("Verifying"));
+ row->setData (FilterMode::SHOW_VERIFYING, ActivityRole);
+ model->appendRow (row);
+
+ row = new QStandardItem (QIcon::fromTheme (QLatin1String ("process-stop")), tr ("Error"));
+ row->setData (FilterMode::SHOW_ERROR, ActivityRole);
+ model->appendRow (row);
+
+ c->setModel (model);
+ return c;
+}
+
+/***
+****
+***/
+
+void
+FilterBar::refreshTrackers ()
+{
+ FaviconCache& favicons = qApp->favicons;
+ const int firstTrackerRow = 2; // skip over the "All" and separator...
+
+ // pull info from the tracker model...
+ QSet<QString> oldHosts;
+ for (int row=firstTrackerRow; ; ++row)
+ {
+ QModelIndex index = myTrackerModel->index (row, 0);
+ if (!index.isValid ())
+ break;
+ oldHosts << index.data (TrackerRole).toString ();
+ }
+
+ // pull the new stats from the torrent model...
+ QSet<QString> newHosts;
+ QMap<QString,int> torrentsPerHost;
+ for (int row=0; ; ++row)
+ {
+ QModelIndex index = myTorrents.index (row, 0);
+ if (!index.isValid ())
+ break;
+ const Torrent * tor = index.data (TorrentModel::TorrentRole).value<const Torrent*> ();
+ QSet<QString> torrentNames;
+ for (const QString& host: tor->hosts ())
+ {
+ newHosts.insert (host);
+ torrentNames.insert (readableHostName (host));
+ }
+ for (const QString& name: torrentNames)
+ ++torrentsPerHost[name];
+ }
+
+ // update the "All" row
+ myTrackerModel->setData (myTrackerModel->index (0,0), myTorrents.rowCount (), FilterBarComboBox::CountRole);
+ myTrackerModel->setData (myTrackerModel->index (0,0), getCountString (myTorrents.rowCount ()), FilterBarComboBox::CountStringRole);
+
+ // rows to update
+ for (const QString& host: oldHosts & newHosts)
+ {
+ const QString name = readableHostName (host);
+ QStandardItem * row = myTrackerModel->findItems (name).front ();
+ const int count = torrentsPerHost[name];
+ row->setData (count, FilterBarComboBox::CountRole);
+ row->setData (getCountString (count), FilterBarComboBox::CountStringRole);
+ row->setData (favicons.findFromHost (host), Qt::DecorationRole);
+ }
+
+ // rows to remove
+ for (const QString& host: oldHosts - newHosts)
+ {
+ const QString name = readableHostName (host);
+ QStandardItem * item = myTrackerModel->findItems (name).front ();
+ if (!item->data (TrackerRole).toString ().isEmpty ()) // don't remove "All"
+ myTrackerModel->removeRows (item->row (), 1);
+ }
+
+ // rows to add
+ bool anyAdded = false;
+ for (const QString& host: newHosts - oldHosts)
+ {
+ const QString name = readableHostName (host);
+
+ if (!myTrackerModel->findItems (name).isEmpty ())
+ continue;
+
+ // find the sorted position to add this row
+ int i = firstTrackerRow;
+ for (int n=myTrackerModel->rowCount (); i<n; ++i)
+ {
+ const QString rowName = myTrackerModel->index (i,0).data (Qt::DisplayRole).toString ();
+ if (rowName >= name)
+ break;
+ }
+
+ // add the row
+ QStandardItem * row = new QStandardItem (favicons.findFromHost (host), name);
+ const int count = torrentsPerHost[host];
+ row->setData (count, FilterBarComboBox::CountRole);
+ row->setData (getCountString (count), FilterBarComboBox::CountStringRole);
+ row->setData (favicons.findFromHost (host), Qt::DecorationRole);
+ row->setData (host, TrackerRole);
+ myTrackerModel->insertRow (i, row);
+ anyAdded = true;
+ }
+
+ if (anyAdded) // the one added might match our filter...
+ refreshPref (Prefs::FILTER_TRACKERS);
+}
+
+
+FilterBarComboBox *
+FilterBar::createTrackerCombo (QStandardItemModel * model)
+{
+ FilterBarComboBox * c = new FilterBarComboBox (this);
+ FilterBarComboBoxDelegate * delegate = new FilterBarComboBoxDelegate (this, c);
+ c->setItemDelegate (delegate);
+
+ QStandardItem * row = new QStandardItem (tr ("All"));
+ row->setData (QString (), TrackerRole);
+ const int count = myTorrents.rowCount ();
+ row->setData (count, FilterBarComboBox::CountRole);
+ row->setData (getCountString (count), FilterBarComboBox::CountStringRole);
+ model->appendRow (row);
+
+ model->appendRow (new QStandardItem); // separator
+ delegate->setSeparator (model, model->index (1, 0));
+
+ c->setModel (model);
+ return c;
+}
+
+/***
+****
+***/
+
+FilterBar::FilterBar (Prefs& prefs, const TorrentModel& torrents, const TorrentFilter& filter, QWidget * parent):
+ QWidget (parent),
+ myPrefs (prefs),
+ myTorrents (torrents),
+ myFilter (filter),
+ myRecountTimer (new QTimer (this)),
+ myIsBootstrapping (true)
+{
+ QHBoxLayout * h = new QHBoxLayout (this);
+ h->setContentsMargins (3, 3, 3, 3);
+
+ myCountLabel = new QLabel (this);
+ h->addWidget (myCountLabel);
+
+ myActivityCombo = createActivityCombo ();
+ myActivityCombo->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
+ h->addWidget (myActivityCombo);
+
+ myTrackerModel = new QStandardItemModel (this);
+ myTrackerCombo = createTrackerCombo (myTrackerModel);
+ h->addWidget (myTrackerCombo);
+
+ myLineEdit = new FilterBarLineEdit (this);
+ h->addWidget (myLineEdit);
+ connect (myLineEdit, SIGNAL (textChanged (QString)), this, SLOT (onTextChanged (QString)));
+
+ // listen for changes from the other players
+ connect (&myPrefs, SIGNAL (changed (int)), this, SLOT (refreshPref (int)));
+ connect (myActivityCombo, SIGNAL (currentIndexChanged (int)), this, SLOT (onActivityIndexChanged (int)));
+ connect (myTrackerCombo, SIGNAL (currentIndexChanged (int)), this, SLOT (onTrackerIndexChanged (int)));
+ connect (&myFilter, SIGNAL (rowsInserted (QModelIndex, int, int)), this, SLOT (refreshCountLabel ()));
+ connect (&myFilter, SIGNAL (rowsRemoved (QModelIndex, int, int)), this, SLOT (refreshCountLabel ()));
+ connect (&myTorrents, SIGNAL (modelReset ()), this, SLOT (onTorrentModelReset ()));
+ connect (&myTorrents, SIGNAL (rowsInserted (QModelIndex, int, int)), this, SLOT (onTorrentModelRowsInserted (QModelIndex, int, int)));
+ connect (&myTorrents, SIGNAL (rowsRemoved (QModelIndex, int, int)), this, SLOT (onTorrentModelRowsRemoved (QModelIndex, int, int)));
+ connect (&myTorrents, SIGNAL (dataChanged (QModelIndex, QModelIndex)), this, SLOT (onTorrentModelDataChanged (QModelIndex, QModelIndex)));
+ connect (myRecountTimer, SIGNAL (timeout ()), this, SLOT (recount ()));
+
+ recountSoon ();
+ refreshTrackers ();
+ refreshCountLabel ();
+ myIsBootstrapping = false;
+
+ // initialize our state
+ QList<int> initKeys;
+ initKeys << Prefs::FILTER_MODE
+ << Prefs::FILTER_TRACKERS;
+ for (const int key: initKeys)
+ refreshPref (key);
+}
+
+FilterBar::~FilterBar ()
+{
+ delete myRecountTimer;
+}
+
+/***
+****
+***/
+
+void
+FilterBar::refreshPref (int key)
+{
+ switch (key)
+ {
+ case Prefs::FILTER_MODE:
+ {
+ const FilterMode m = myPrefs.get<FilterMode> (key);
+ QAbstractItemModel * model = myActivityCombo->model ();
+ QModelIndexList indices = model->match (model->index (0,0), ActivityRole, m.mode ());
+ myActivityCombo->setCurrentIndex (indices.isEmpty () ? 0 : indices.first ().row ());
+ break;
+ }
+
+ case Prefs::FILTER_TRACKERS:
+ {
+ const QString tracker = myPrefs.getString (key);
+ const QString name = readableHostName (tracker);
+ QList<QStandardItem*> rows = myTrackerModel->findItems (name);
+ if (!rows.isEmpty ())
+ {
+ myTrackerCombo->setCurrentIndex (rows.front ()->row ());
+ }
+ else // hm, we don't seem to have this tracker anymore...
+ {
+ const bool isBootstrapping = myTrackerModel->rowCount () <= 2;
+ if (!isBootstrapping)
+ myPrefs.set (key, QString ());
+ }
+ break;
+ }
+ }
+}
+
+void
+FilterBar::onTextChanged (const QString& str)
+{
+ if (!myIsBootstrapping)
+ myPrefs.set (Prefs::FILTER_TEXT, str.trimmed ());
+}
+
+void
+FilterBar::onTrackerIndexChanged (int i)
+{
+ if (!myIsBootstrapping)
+ {
+ QString str;
+ const bool isTracker = !myTrackerCombo->itemData (i,TrackerRole).toString ().isEmpty ();
+ if (!isTracker)
+ {
+ // show all
+ }
+ else
+ {
+ str = myTrackerCombo->itemData (i,TrackerRole).toString ();
+ const int pos = str.lastIndexOf (QLatin1Char ('.'));
+ if (pos >= 0)
+ str.truncate (pos+1);
+ }
+ myPrefs.set (Prefs::FILTER_TRACKERS, str);
+ }
+}
+
+void
+FilterBar::onActivityIndexChanged (int i)
+{
+ if (!myIsBootstrapping)
+ {
+ const FilterMode mode = myActivityCombo->itemData (i, ActivityRole).toInt ();
+ myPrefs.set (Prefs::FILTER_MODE, mode);
+ }
+}
+
+/***
+****
+***/
+
+void FilterBar::onTorrentModelReset () { recountSoon (); }
+void FilterBar::onTorrentModelRowsInserted (const QModelIndex&, int, int) { recountSoon (); }
+void FilterBar::onTorrentModelRowsRemoved (const QModelIndex&, int, int) { recountSoon (); }
+void FilterBar::onTorrentModelDataChanged (const QModelIndex&, const QModelIndex&) { recountSoon (); }
+
+void
+FilterBar::recountSoon ()
+{
+ if (!myRecountTimer->isActive ())
+ {
+ myRecountTimer->setSingleShot (true);
+ myRecountTimer->start (800);
+ }
+}
+void
+FilterBar::recount ()
+{
+ QAbstractItemModel * model = myActivityCombo->model ();
+
+ int torrentsPerMode[FilterMode::NUM_MODES] = {};
+ myFilter.countTorrentsPerMode (torrentsPerMode);
+
+ for (int row=0, n=model->rowCount (); row<n; ++row)
+ {
+ QModelIndex index = model->index (row, 0);
+ const int mode = index.data (ActivityRole).toInt ();
+ const int count = torrentsPerMode [mode];
+ model->setData (index, count, FilterBarComboBox::CountRole);
+ model->setData (index, getCountString (count), FilterBarComboBox::CountStringRole);
+ }
+
+ refreshTrackers ();
+ refreshCountLabel ();
+}
+
+QString
+FilterBar::getCountString (int n) const
+{
+ return QString::fromLatin1 ("%L1").arg (n);
+}
+
+void
+FilterBar::refreshCountLabel ()
+{
+ const int visibleCount = myFilter.rowCount ();
+ const int trackerCount = myTrackerCombo->currentCount ();
+ const int activityCount = myActivityCombo->currentCount ();
+
+ if ((visibleCount == activityCount) || (visibleCount == trackerCount))
+ myCountLabel->setText (tr("Show:"));
+ else
+ myCountLabel->setText (tr("Show %Ln of:", 0, visibleCount));
+}
/*
- * This file Copyright (C) 2010-2014 Mnemosyne LLC
+ * This file Copyright (C) 2010-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef QTR_FILTERBAR_H
-#define QTR_FILTERBAR_H
+#ifndef QTR_FILTER_BAR_H
+#define QTR_FILTER_BAR_H
-#include <QComboBox>
-#include <QItemDelegate>
-#include <QLineEdit>
#include <QWidget>
class QLabel;
-class QLineEdit;
-class QPaintEvent;
class QStandardItemModel;
class QTimer;
-class QToolButton;
+class FilterBarComboBox;
+class FilterBarLineEdit;
class Prefs;
class TorrentFilter;
class TorrentModel;
-class FilterBarComboBoxDelegate: public QItemDelegate
-{
- Q_OBJECT
-
- public:
- FilterBarComboBoxDelegate (QObject * parent, QComboBox * combo);
-
- public:
- static bool isSeparator (const QModelIndex &index);
- static void setSeparator (QAbstractItemModel * model, const QModelIndex& index);
-
- protected:
- virtual void paint (QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const;
- virtual QSize sizeHint (const QStyleOptionViewItem&, const QModelIndex&) const;
-
- private:
- QComboBox * myCombo;
-
-};
-
-class FilterBarComboBox: public QComboBox
-{
- Q_OBJECT
-
- public:
- FilterBarComboBox (QWidget * parent = 0);
- int currentCount () const;
-
- virtual QSize minimumSizeHint () const;
- virtual QSize sizeHint () const;
-
- protected:
- virtual void paintEvent (QPaintEvent * e);
-
- private:
- QSize calculateSize (const QSize& textSize, const QSize& countSize) const;
-};
-
-class FilterBarLineEdit: public QLineEdit
-{
- Q_OBJECT
-
- public:
- FilterBarLineEdit (QWidget * parent = 0);
-
- protected:
- virtual void resizeEvent (QResizeEvent * event);
-
- private slots:
- void updateClearButtonVisibility ();
-
- private:
- QToolButton * myClearButton;
-};
-
class FilterBar: public QWidget
{
Q_OBJECT
void onTextChanged (const QString&);
};
-#endif
+#endif // QTR_FILTER_BAR_H
--- /dev/null
+/*
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#include <QApplication>
+#include <QStyle>
+#include <QStylePainter>
+
+#include "FilterBarComboBox.h"
+#include "Utils.h"
+
+namespace
+{
+ int
+ getHSpacing (const QWidget * w)
+ {
+ return qMax (3, w->style ()->pixelMetric (QStyle::PM_LayoutHorizontalSpacing, 0, w));
+ }
+}
+
+FilterBarComboBox::FilterBarComboBox (QWidget * parent):
+ QComboBox (parent)
+{
+ setSizeAdjustPolicy (QComboBox::AdjustToContents);
+}
+
+int
+FilterBarComboBox::currentCount () const
+{
+ int count = 0;
+
+ const QModelIndex modelIndex = model ()->index (currentIndex (), 0, rootModelIndex ());
+ if (modelIndex.isValid ())
+ count = modelIndex.data (CountRole).toInt ();
+
+ return count;
+}
+
+QSize
+FilterBarComboBox::minimumSizeHint () const
+{
+ QFontMetrics fm (fontMetrics ());
+ const QSize textSize = fm.boundingRect (itemText (0)).size ();
+ const QSize countSize = fm.boundingRect (itemData (0, CountStringRole).toString ()).size ();
+ return calculateSize (textSize, countSize);
+}
+
+QSize
+FilterBarComboBox::sizeHint () const
+{
+ QFontMetrics fm (fontMetrics ());
+ QSize maxTextSize (0, 0);
+ QSize maxCountSize (0, 0);
+ for (int i = 0, n = count (); i < n; ++i)
+ {
+ const QSize textSize = fm.boundingRect (itemText (i)).size ();
+ maxTextSize.setHeight (qMax (maxTextSize.height (), textSize.height ()));
+ maxTextSize.setWidth (qMax (maxTextSize.width (), textSize.width ()));
+
+ const QSize countSize = fm.boundingRect (itemData (i, CountStringRole).toString ()).size ();
+ maxCountSize.setHeight (qMax (maxCountSize.height (), countSize.height ()));
+ maxCountSize.setWidth (qMax (maxCountSize.width (), countSize.width ()));
+ }
+
+ return calculateSize (maxTextSize, maxCountSize);
+}
+
+QSize
+FilterBarComboBox::calculateSize (const QSize& textSize, const QSize& countSize) const
+{
+ const int hmargin = getHSpacing (this);
+
+ QStyleOptionComboBox option;
+ initStyleOption (&option);
+
+ QSize contentSize = iconSize () + QSize (4, 2);
+ contentSize.setHeight (qMax (contentSize.height (), textSize.height ()));
+ contentSize.rwidth () += hmargin + textSize.width ();
+ contentSize.rwidth () += hmargin + countSize.width ();
+
+ return style ()->sizeFromContents (QStyle::CT_ComboBox, &option, contentSize, this).expandedTo (qApp->globalStrut ());
+}
+
+void
+FilterBarComboBox::paintEvent (QPaintEvent * e)
+{
+ Q_UNUSED (e);
+
+ QStylePainter painter (this);
+ painter.setPen (palette ().color (QPalette::Text));
+
+ // draw the combobox frame, focusrect and selected etc.
+ QStyleOptionComboBox opt;
+ initStyleOption (&opt);
+ painter.drawComplexControl (QStyle::CC_ComboBox, opt);
+
+ // draw the icon and text
+ const QModelIndex modelIndex = model ()->index (currentIndex (), 0, rootModelIndex ());
+ if (modelIndex.isValid ())
+ {
+ QStyle * s = style ();
+ const int hmargin = getHSpacing (this);
+
+ QRect rect = s->subControlRect (QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);
+ rect.adjust (2, 1, -2, -1);
+
+ // draw the icon
+ QPixmap pixmap;
+ QVariant variant = modelIndex.data (Qt::DecorationRole);
+ switch (variant.type ())
+ {
+ case QVariant::Pixmap: pixmap = qvariant_cast<QPixmap> (variant); break;
+ case QVariant::Icon: pixmap = qvariant_cast<QIcon> (variant).pixmap (iconSize ()); break;
+ default: break;
+ }
+ if (!pixmap.isNull ())
+ {
+ const QRect iconRect = QStyle::alignedRect(opt.direction, Qt::AlignLeft | Qt::AlignVCenter,
+ opt.iconSize, rect);
+ painter.drawPixmap (iconRect.topLeft (), pixmap);
+ Utils::narrowRect (rect, iconRect.width () + hmargin, 0, opt.direction);
+ }
+
+ // draw the count
+ QString text = modelIndex.data (CountStringRole).toString ();
+ if (!text.isEmpty ())
+ {
+ const QPen pen = painter.pen ();
+ painter.setPen (Utils::getFadedColor (pen.color ()));
+ const QRect textRect = QStyle::alignedRect(opt.direction, Qt::AlignRight | Qt::AlignVCenter,
+ QSize (opt.fontMetrics.width (text), rect.height ()), rect);
+ painter.drawText (textRect, Qt::AlignRight | Qt::AlignVCenter, text);
+ Utils::narrowRect (rect, 0, textRect.width () + hmargin, opt.direction);
+ painter.setPen (pen);
+ }
+
+ // draw the text
+ text = modelIndex.data (Qt::DisplayRole).toString ();
+ text = painter.fontMetrics ().elidedText (text, Qt::ElideRight, rect.width ());
+ painter.drawText (rect, Qt::AlignLeft | Qt::AlignVCenter, text);
+ }
+}
--- /dev/null
+/*
+ * This file Copyright (C) 2010-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#ifndef QTR_FILTER_BAR_COMBO_BOX_H
+#define QTR_FILTER_BAR_COMBO_BOX_H
+
+#include <QComboBox>
+
+class FilterBarComboBox: public QComboBox
+{
+ Q_OBJECT
+
+ public:
+ enum
+ {
+ CountRole = Qt::UserRole + 1,
+ CountStringRole,
+ UserRole
+ };
+
+ public:
+ FilterBarComboBox (QWidget * parent = 0);
+ int currentCount () const;
+
+ virtual QSize minimumSizeHint () const;
+ virtual QSize sizeHint () const;
+
+ protected:
+ virtual void paintEvent (QPaintEvent * e);
+
+ private:
+ QSize calculateSize (const QSize& textSize, const QSize& countSize) const;
+};
+
+#endif // QTR_FILTER_BAR_COMBO_BOX_H
--- /dev/null
+/*
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#include <QAbstractItemView>
+#include <QComboBox>
+#include <QStandardItemModel>
+#include <QStyle>
+
+#include "FilterBarComboBox.h"
+#include "FilterBarComboBoxDelegate.h"
+#include "Utils.h"
+
+namespace
+{
+ int
+ getHSpacing (const QWidget * w)
+ {
+ return qMax (3, w->style ()->pixelMetric (QStyle::PM_LayoutHorizontalSpacing, 0, w));
+ }
+}
+
+FilterBarComboBoxDelegate::FilterBarComboBoxDelegate (QObject * parent, QComboBox * combo):
+ QItemDelegate (parent),
+ myCombo (combo)
+{
+}
+
+bool
+FilterBarComboBoxDelegate::isSeparator (const QModelIndex& index)
+{
+ return index.data (Qt::AccessibleDescriptionRole).toString () == QLatin1String ("separator");
+}
+void
+FilterBarComboBoxDelegate::setSeparator (QAbstractItemModel * model, const QModelIndex& index)
+{
+ model->setData (index, QString::fromLatin1 ("separator"), Qt::AccessibleDescriptionRole);
+
+ if (QStandardItemModel *m = qobject_cast<QStandardItemModel*> (model))
+ if (QStandardItem *item = m->itemFromIndex (index))
+ item->setFlags (item->flags () & ~ (Qt::ItemIsSelectable|Qt::ItemIsEnabled));
+}
+
+void
+FilterBarComboBoxDelegate::paint (QPainter * painter,
+ const QStyleOptionViewItem & option,
+ const QModelIndex & index) const
+{
+ if (isSeparator (index))
+ {
+ QRect rect = option.rect;
+ if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3*> (&option))
+ if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView*> (v3->widget))
+ rect.setWidth (view->viewport ()->width ());
+ QStyleOption opt;
+ opt.rect = rect;
+ myCombo->style ()->drawPrimitive (QStyle::PE_IndicatorToolBarSeparator, &opt, painter, myCombo);
+ }
+ else
+ {
+ QStyleOptionViewItem disabledOption = option;
+ const QPalette::ColorRole disabledColorRole = (disabledOption.state & QStyle::State_Selected) ?
+ QPalette::HighlightedText : QPalette::Text;
+ disabledOption.palette.setColor (disabledColorRole, Utils::getFadedColor (disabledOption.palette.color (disabledColorRole)));
+
+ QRect boundingBox = option.rect;
+
+ const int hmargin = getHSpacing (myCombo);
+ boundingBox.adjust (hmargin, 0, -hmargin, 0);
+
+ QRect decorationRect = rect (option, index, Qt::DecorationRole);
+ decorationRect.setSize (myCombo->iconSize ());
+ decorationRect = QStyle::alignedRect (option.direction,
+ Qt::AlignLeft|Qt::AlignVCenter,
+ decorationRect.size (), boundingBox);
+ Utils::narrowRect (boundingBox, decorationRect.width () + hmargin, 0, option.direction);
+
+ QRect countRect = rect (option, index, FilterBarComboBox::CountStringRole);
+ countRect = QStyle::alignedRect (option.direction,
+ Qt::AlignRight|Qt::AlignVCenter,
+ countRect.size (), boundingBox);
+ Utils::narrowRect (boundingBox, 0, countRect.width () + hmargin, option.direction);
+ const QRect displayRect = boundingBox;
+
+ drawBackground (painter, option, index);
+ QStyleOptionViewItem option2 = option;
+ option2.decorationSize = myCombo->iconSize ();
+ drawDecoration (painter, option, decorationRect, decoration (option2,index.data (Qt::DecorationRole)));
+ drawDisplay (painter, option, displayRect, index.data (Qt::DisplayRole).toString ());
+ drawDisplay (painter, disabledOption, countRect, index.data (FilterBarComboBox::CountStringRole).toString ());
+ drawFocus (painter, option, displayRect|countRect);
+ }
+}
+
+QSize
+FilterBarComboBoxDelegate::sizeHint (const QStyleOptionViewItem & option,
+ const QModelIndex & index) const
+{
+ if (isSeparator (index))
+ {
+ const int pm = myCombo->style ()->pixelMetric (QStyle::PM_DefaultFrameWidth, 0, myCombo);
+ return QSize (pm, pm + 10);
+ }
+ else
+ {
+ QStyle * s = myCombo->style ();
+ const int hmargin = getHSpacing (myCombo);
+
+ QSize size = QItemDelegate::sizeHint (option, index);
+ size.setHeight (qMax (size.height (), myCombo->iconSize ().height () + 6));
+ size.rwidth () += s->pixelMetric (QStyle::PM_FocusFrameHMargin, 0, myCombo);
+ size.rwidth () += rect (option,index,FilterBarComboBox::CountStringRole).width ();
+ size.rwidth () += hmargin * 4;
+ return size;
+ }
+}
--- /dev/null
+/*
+ * This file Copyright (C) 2010-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#ifndef QTR_FILTER_BAR_COMBO_BOX_DELEGATE_H
+#define QTR_FILTER_BAR_COMBO_BOX_DELEGATE_H
+
+#include <QItemDelegate>
+
+class QAbstractItemModel;
+class QComboBox;
+
+class FilterBarComboBoxDelegate: public QItemDelegate
+{
+ Q_OBJECT
+
+ public:
+ FilterBarComboBoxDelegate (QObject * parent, QComboBox * combo);
+
+ public:
+ static bool isSeparator (const QModelIndex &index);
+ static void setSeparator (QAbstractItemModel * model, const QModelIndex& index);
+
+ protected:
+ virtual void paint (QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const;
+ virtual QSize sizeHint (const QStyleOptionViewItem&, const QModelIndex&) const;
+
+ private:
+ QComboBox * myCombo;
+};
+
+#endif // QTR_FILTER_BAR_COMBO_BOX_DELEGATE_H
--- /dev/null
+/*
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#include <QToolButton>
+#include <QStyle>
+
+#include "FilterBarLineEdit.h"
+
+FilterBarLineEdit::FilterBarLineEdit (QWidget * parent):
+ QLineEdit (parent),
+ myClearButton (nullptr)
+{
+#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+ const QIcon icon = QIcon::fromTheme (QLatin1String ("edit-clear"), style ()->standardIcon (QStyle::SP_DialogCloseButton));
+ const int iconSize = style ()->pixelMetric (QStyle::PM_SmallIconSize);
+
+ myClearButton = new QToolButton (this);
+ myClearButton->setStyleSheet (QLatin1String ("QToolButton{border:0;padding:0;margin:0}"));
+ myClearButton->setToolButtonStyle (Qt::ToolButtonIconOnly);
+ myClearButton->setFocusPolicy (Qt::NoFocus);
+ myClearButton->setCursor (Qt::ArrowCursor);
+ myClearButton->setIconSize (QSize (iconSize, iconSize));
+ myClearButton->setIcon (icon);
+ myClearButton->setFixedSize (myClearButton->iconSize () + QSize (2, 2));
+ myClearButton->hide ();
+
+ const int frameWidth = style ()->pixelMetric (QStyle::PM_DefaultFrameWidth);
+ const QSize minSizeHint = minimumSizeHint ();
+ const QSize buttonSize = myClearButton->size ();
+
+ setStyleSheet (QString::fromLatin1 ("QLineEdit{padding-right:%1px}").arg (buttonSize.width () + frameWidth + 1));
+ setMinimumSize (qMax (minSizeHint.width (), buttonSize.width () + frameWidth * 2 + 2),
+ qMax (minSizeHint.height (), buttonSize.height () + frameWidth * 2 + 2));
+
+ connect (this, SIGNAL (textChanged (QString)), this, SLOT (updateClearButtonVisibility ()));
+ connect (myClearButton, SIGNAL (clicked ()), this, SLOT (clear ()));
+#else
+ setClearButtonEnabled (true);
+#endif
+
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+ setPlaceholderText (tr ("Search..."));
+#endif
+}
+
+void
+FilterBarLineEdit::resizeEvent (QResizeEvent * event)
+{
+ QLineEdit::resizeEvent (event);
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+ const int frameWidth = style ()->pixelMetric (QStyle::PM_DefaultFrameWidth);
+ const QRect editRect = rect();
+ const QSize buttonSize = myClearButton->size ();
+
+ myClearButton->move (editRect.right () - frameWidth - buttonSize.width (),
+ editRect.top () + (editRect.height () - buttonSize.height ()) / 2);
+#endif
+}
+
+void
+FilterBarLineEdit::updateClearButtonVisibility ()
+{
+#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
+ myClearButton->setVisible (!text ().isEmpty ());
+#endif
+}
--- /dev/null
+/*
+ * This file Copyright (C) 2010-2015 Mnemosyne LLC
+ *
+ * It may be used under the GNU GPL versions 2 or 3
+ * or any future license endorsed by Mnemosyne LLC.
+ *
+ * $Id$
+ */
+
+#ifndef QTR_FILTER_BAR_LINE_EDIT_H
+#define QTR_FILTER_BAR_LINE_EDIT_H
+
+#include <QLineEdit>
+
+class QToolButton;
+
+class FilterBarLineEdit: public QLineEdit
+{
+ Q_OBJECT
+
+ public:
+ FilterBarLineEdit (QWidget * parent = 0);
+
+ protected:
+ virtual void resizeEvent (QResizeEvent * event);
+
+ private slots:
+ void updateClearButtonVisibility ();
+
+ private:
+ QToolButton * myClearButton;
+};
+
+#endif // QTR_FILTER_BAR_LINE_EDIT_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#include "filters.h"
+#include "Filters.h"
const QString FilterMode::names[NUM_MODES] =
{
/*
- * This file Copyright (C) 2010-2014 Mnemosyne LLC
+ * This file Copyright (C) 2010-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
Q_DECLARE_METATYPE(FilterMode)
Q_DECLARE_METATYPE(SortMode)
-#endif
+#endif // QTR_FILTERS_H
/*
- * This file Copyright (C) 2012-2014 Mnemosyne LLC
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h> // tr_formatter
-#include "formatter.h"
-#include "speed.h"
+#include "Formatter.h"
+#include "Speed.h"
/***
**** Constants
/*
- * This file Copyright (C) 2012-2014 Mnemosyne LLC
+ * This file Copyright (C) 2012-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef QTR_UNITS
-#define QTR_UNITS
+#ifndef QTR_FORMATTER_H
+#define QTR_FORMATTER_H
+
+#include <stdint.h> // int64_t
#include <QString>
#include <QObject>
#include <QIcon>
-#include <stdint.h> // int64_t
-
class Speed;
class Formatter: public QObject
static QString unitStrings[3][5];
};
-#endif
+#endif // QTR_FORMATTER_H
/*
- * This file Copyright (C) 2013-2014 Mnemosyne LLC
+ * This file Copyright (C) 2013-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/transmission.h>
#include <libtransmission/variant.h>
-#include "formatter.h"
-#include "freespace-label.h"
-#include "session.h"
+#include "Formatter.h"
+#include "FreeSpaceLabel.h"
+#include "Session.h"
namespace
{
static const int INTERVAL_MSEC = 15000;
}
-FreespaceLabel::FreespaceLabel (QWidget * parent):
+FreeSpaceLabel::FreeSpaceLabel (QWidget * parent):
QLabel (parent),
mySession (nullptr),
myTag (-1),
}
void
-FreespaceLabel::setSession (Session& session)
+FreeSpaceLabel::setSession (Session& session)
{
if (mySession == &session)
return;
}
void
-FreespaceLabel::setPath (const QString& path)
+FreeSpaceLabel::setPath (const QString& path)
{
if (myPath != path)
{
}
void
-FreespaceLabel::onTimer ()
+FreeSpaceLabel::onTimer ()
{
myTimer.stop ();
}
void
-FreespaceLabel::onSessionExecuted (int64_t tag, const QString& result, tr_variant * arguments)
+FreeSpaceLabel::onSessionExecuted (int64_t tag, const QString& result, tr_variant * arguments)
{
Q_UNUSED (result);
/*
- * This file Copyright (C) 2013-2014 Mnemosyne LLC
+ * This file Copyright (C) 2013-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef QTR_FREESPACE_LABEL_H
-#define QTR_FREESPACE_LABEL_H
+#ifndef QTR_FREE_SPACE_LABEL_H
+#define QTR_FREE_SPACE_LABEL_H
#include <stdint.h>
struct tr_variant;
}
-class FreespaceLabel: public QLabel
+class FreeSpaceLabel: public QLabel
{
Q_OBJECT
public:
- FreespaceLabel (QWidget * parent = 0);
- virtual ~FreespaceLabel () {}
+ FreeSpaceLabel (QWidget * parent = 0);
+ virtual ~FreeSpaceLabel () {}
void setSession (Session& session);
void setPath (const QString& folder);
void onTimer ();
};
-#endif // QTR_FREESPACE_LABEL_H
-
+#endif // QTR_FREE_SPACE_LABEL_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QStyleOptionToolButton>
#include <QStylePainter>
-#include "tricontoolbutton.h"
+#include "IconToolButton.h"
-TrIconToolButton::TrIconToolButton (QWidget * parent):
+IconToolButton::IconToolButton (QWidget * parent):
QToolButton (parent)
{
}
-void TrIconToolButton::paintEvent (QPaintEvent * /*event*/)
+void IconToolButton::paintEvent (QPaintEvent * /*event*/)
{
QStylePainter painter(this);
QStyleOptionToolButton option;
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QToolButton>
-class TrIconToolButton: public QToolButton
+class IconToolButton: public QToolButton
{
Q_OBJECT
public:
- TrIconToolButton (QWidget * parent = nullptr);
+ IconToolButton (QWidget * parent = nullptr);
protected:
virtual void paintEvent (QPaintEvent * event);
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QPlainTextEdit>
#include <QVBoxLayout>
-#include "license.h"
+#include "LicenseDialog.h"
LicenseDialog::LicenseDialog (QWidget * parent):
QDialog (parent, Qt::Dialog)
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef LICENSE_DIALOG_H
-#define LICENSE_DIALOG_H
+#ifndef QTR_LICENSE_DIALOG_H
+#define QTR_LICENSE_DIALOG_H
#include <QDialog>
~LicenseDialog () {}
};
-#endif
-
+#endif // QTR_LICENSE_DIALOG_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/transmission.h>
#include <libtransmission/version.h>
-#include "about.h"
-#include "add-data.h"
-#include "app.h"
-#include "details.h"
-#include "filterbar.h"
-#include "filters.h"
-#include "formatter.h"
-#include "hig.h"
-#include "mainwin.h"
-#include "make-dialog.h"
-#include "options.h"
-#include "prefs.h"
-#include "prefs-dialog.h"
-#include "relocate.h"
-#include "session.h"
-#include "session-dialog.h"
-#include "speed.h"
-#include "stats-dialog.h"
-#include "torrent-delegate.h"
-#include "torrent-delegate-min.h"
-#include "torrent-filter.h"
-#include "torrent-model.h"
+#include "AboutDialog.h"
+#include "AddData.h"
+#include "Application.h"
+#include "DetailsDialog.h"
+#include "FilterBar.h"
+#include "Filters.h"
+#include "Formatter.h"
+#include "MainWindow.h"
+#include "MakeDialog.h"
+#include "OptionsDialog.h"
+#include "Prefs.h"
+#include "PrefsDialog.h"
+#include "RelocateDialog.h"
+#include "Session.h"
+#include "SessionDialog.h"
+#include "Speed.h"
+#include "StatsDialog.h"
+#include "TorrentDelegate.h"
+#include "TorrentDelegateMin.h"
+#include "TorrentFilter.h"
+#include "TorrentModel.h"
#define PREFS_KEY "prefs-key";
QIcon
-TrMainWindow::getStockIcon (const QString& name, int fallback)
+MainWindow::getStockIcon (const QString& name, int fallback)
{
QIcon icon = QIcon::fromTheme (name);
return icon;
}
-TrMainWindow::TrMainWindow (Session& session, Prefs& prefs, TorrentModel& model, bool minimized):
+MainWindow::MainWindow (Session& session, Prefs& prefs, TorrentModel& model, bool minimized):
myLastFullUpdateTime (0),
mySessionDialog (new SessionDialog (session, prefs, this)),
myPrefsDialog (),
refreshTitle ();
}
-TrMainWindow::~TrMainWindow ()
+MainWindow::~MainWindow ()
{
}
****/
void
-TrMainWindow::onSessionSourceChanged ()
+MainWindow::onSessionSourceChanged ()
{
myModel.clear ();
}
void
-TrMainWindow::onModelReset ()
+MainWindow::onModelReset ()
{
refreshTitle ();
refreshActionSensitivitySoon ();
#define PREF_VARIANTS_KEY "pref-variants-list"
void
-TrMainWindow::onSetPrefs ()
+MainWindow::onSetPrefs ()
{
const QVariantList p = sender ()->property (PREF_VARIANTS_KEY).toList ();
assert ( (p.size () % 2) == 0);
}
void
-TrMainWindow::onSetPrefs (bool isChecked)
+MainWindow::onSetPrefs (bool isChecked)
{
if (isChecked)
onSetPrefs ();
#define SHOW_KEY "show-mode"
void
-TrMainWindow::initStatusBar ()
+MainWindow::initStatusBar ()
{
ui.optionsButton->setMenu (createOptionsMenu ());
}
QMenu *
-TrMainWindow::createOptionsMenu ()
+MainWindow::createOptionsMenu ()
{
QMenu * menu;
QMenu * sub;
}
QMenu *
-TrMainWindow::createStatsModeMenu ()
+MainWindow::createStatsModeMenu ()
{
QActionGroup * a = new QActionGroup (this);
a->addAction (ui.action_TotalRatio);
****/
void
-TrMainWindow::setSortPref (int i)
+MainWindow::setSortPref (int i)
{
myPrefs.set (Prefs::SORT_MODE, SortMode (i));
}
-void TrMainWindow::onSortByActivityToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_ACTIVITY); }
-void TrMainWindow::onSortByAgeToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_AGE); }
-void TrMainWindow::onSortByETAToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_ETA); }
-void TrMainWindow::onSortByNameToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_NAME); }
-void TrMainWindow::onSortByProgressToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_PROGRESS); }
-void TrMainWindow::onSortByQueueToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_QUEUE); }
-void TrMainWindow::onSortByRatioToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_RATIO); }
-void TrMainWindow::onSortBySizeToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_SIZE); }
-void TrMainWindow::onSortByStateToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_STATE); }
+void MainWindow::onSortByActivityToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_ACTIVITY); }
+void MainWindow::onSortByAgeToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_AGE); }
+void MainWindow::onSortByETAToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_ETA); }
+void MainWindow::onSortByNameToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_NAME); }
+void MainWindow::onSortByProgressToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_PROGRESS); }
+void MainWindow::onSortByQueueToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_QUEUE); }
+void MainWindow::onSortByRatioToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_RATIO); }
+void MainWindow::onSortBySizeToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_SIZE); }
+void MainWindow::onSortByStateToggled (bool b) { if (b) setSortPref (SortMode::SORT_BY_STATE); }
void
-TrMainWindow::setSortAscendingPref (bool b)
+MainWindow::setSortAscendingPref (bool b)
{
myPrefs.set (Prefs::SORT_REVERSED, b);
}
****/
void
-TrMainWindow::showEvent (QShowEvent * event)
+MainWindow::showEvent (QShowEvent * event)
{
Q_UNUSED (event);
****/
void
-TrMainWindow::hideEvent (QHideEvent * event)
+MainWindow::hideEvent (QHideEvent * event)
{
Q_UNUSED (event);
****/
void
-TrMainWindow::openPreferences ()
+MainWindow::openPreferences ()
{
if (myPrefsDialog.isNull ())
{
}
void
-TrMainWindow::onDetailsDestroyed ()
+MainWindow::onDetailsDestroyed ()
{
myDetailsDialog = 0;
}
void
-TrMainWindow::openProperties ()
+MainWindow::openProperties ()
{
if (myDetailsDialog == 0)
{
- myDetailsDialog = new Details (mySession, myPrefs, myModel, this);
+ myDetailsDialog = new DetailsDialog (mySession, myPrefs, myModel, this);
connect (myDetailsDialog, SIGNAL (destroyed (QObject*)), this, SLOT (onDetailsDestroyed ()));
}
}
void
-TrMainWindow::setLocation ()
+MainWindow::setLocation ()
{
QDialog * d = new RelocateDialog (mySession, myModel, getSelectedTorrents (), this);
d->setAttribute (Qt::WA_DeleteOnClose, true);
#endif
void
-TrMainWindow::openFolder ()
+MainWindow::openFolder ()
{
const int torrentId (*getSelectedTorrents ().begin ());
const Torrent * tor (myModel.getTorrentFromId (torrentId));
}
void
-TrMainWindow::copyMagnetLinkToClipboard ()
+MainWindow::copyMagnetLinkToClipboard ()
{
const int id (*getSelectedTorrents ().begin ());
mySession.copyMagnetLinkToClipboard (id);
}
void
-TrMainWindow::openDonate ()
+MainWindow::openDonate ()
{
QDesktopServices::openUrl (QUrl (QLatin1String ("http://www.transmissionbt.com/donate.php")));
}
void
-TrMainWindow::openHelp ()
+MainWindow::openHelp ()
{
QDesktopServices::openUrl (QUrl (QString::fromLatin1 ("http://www.transmissionbt.com/help/gtk/%1.%2x").
arg (MAJOR_VERSION).arg (MINOR_VERSION / 10)));
}
void
-TrMainWindow::refreshTitle ()
+MainWindow::refreshTitle ()
{
QString title (QLatin1String ("Transmission"));
const QUrl url (mySession.getRemoteUrl ());
}
void
-TrMainWindow::refreshTrayIconSoon ()
+MainWindow::refreshTrayIconSoon ()
{
if (!myRefreshTrayIconTimer.isActive ())
{
}
}
void
-TrMainWindow::refreshTrayIcon ()
+MainWindow::refreshTrayIcon ()
{
Speed upSpeed, downSpeed;
size_t upCount, downCount;
}
void
-TrMainWindow::refreshStatusBar ()
+MainWindow::refreshStatusBar ()
{
Speed upSpeed, downSpeed;
size_t upCount, downCount;
void
-TrMainWindow::refreshActionSensitivitySoon ()
+MainWindow::refreshActionSensitivitySoon ()
{
if (!myRefreshActionSensitivityTimer.isActive ())
{
}
}
void
-TrMainWindow::refreshActionSensitivity ()
+MainWindow::refreshActionSensitivity ()
{
int selected (0);
int paused (0);
**/
void
-TrMainWindow::clearSelection ()
+MainWindow::clearSelection ()
{
ui.action_DeselectAll->trigger ();
}
QSet<int>
-TrMainWindow::getSelectedTorrents () const
+MainWindow::getSelectedTorrents () const
{
QSet<int> ids;
}
void
-TrMainWindow::startSelected ()
+MainWindow::startSelected ()
{
mySession.startTorrents (getSelectedTorrents ());
}
void
-TrMainWindow::startSelectedNow ()
+MainWindow::startSelectedNow ()
{
mySession.startTorrentsNow (getSelectedTorrents ());
}
void
-TrMainWindow::pauseSelected ()
+MainWindow::pauseSelected ()
{
mySession.pauseTorrents (getSelectedTorrents ());
}
void
-TrMainWindow::queueMoveTop ()
+MainWindow::queueMoveTop ()
{
mySession.queueMoveTop (getSelectedTorrents ());
}
void
-TrMainWindow::queueMoveUp ()
+MainWindow::queueMoveUp ()
{
mySession.queueMoveUp (getSelectedTorrents ());
}
void
-TrMainWindow::queueMoveDown ()
+MainWindow::queueMoveDown ()
{
mySession.queueMoveDown (getSelectedTorrents ());
}
void
-TrMainWindow::queueMoveBottom ()
+MainWindow::queueMoveBottom ()
{
mySession.queueMoveBottom (getSelectedTorrents ());
}
void
-TrMainWindow::startAll ()
+MainWindow::startAll ()
{
mySession.startTorrents ();
}
void
-TrMainWindow::pauseAll ()
+MainWindow::pauseAll ()
{
mySession.pauseTorrents ();
}
void
-TrMainWindow::removeSelected ()
+MainWindow::removeSelected ()
{
removeTorrents (false);
}
void
-TrMainWindow::deleteSelected ()
+MainWindow::deleteSelected ()
{
removeTorrents (true);
}
void
-TrMainWindow::verifySelected ()
+MainWindow::verifySelected ()
{
mySession.verifyTorrents (getSelectedTorrents ());
}
void
-TrMainWindow::reannounceSelected ()
+MainWindow::reannounceSelected ()
{
mySession.reannounceTorrents (getSelectedTorrents ());
}
***
**/
-void TrMainWindow::showTotalRatio () { myPrefs.set (Prefs::STATUSBAR_STATS, QString::fromLatin1 ("total-ratio")); }
-void TrMainWindow::showTotalTransfer () { myPrefs.set (Prefs::STATUSBAR_STATS, QString::fromLatin1 ("total-transfer")); }
-void TrMainWindow::showSessionRatio () { myPrefs.set (Prefs::STATUSBAR_STATS, QString::fromLatin1 ("session-ratio")); }
-void TrMainWindow::showSessionTransfer () { myPrefs.set (Prefs::STATUSBAR_STATS, QString::fromLatin1 ("session-transfer")); }
+void MainWindow::showTotalRatio () { myPrefs.set (Prefs::STATUSBAR_STATS, QString::fromLatin1 ("total-ratio")); }
+void MainWindow::showTotalTransfer () { myPrefs.set (Prefs::STATUSBAR_STATS, QString::fromLatin1 ("total-transfer")); }
+void MainWindow::showSessionRatio () { myPrefs.set (Prefs::STATUSBAR_STATS, QString::fromLatin1 ("session-ratio")); }
+void MainWindow::showSessionTransfer () { myPrefs.set (Prefs::STATUSBAR_STATS, QString::fromLatin1 ("session-transfer")); }
/**
***
**/
void
-TrMainWindow::setCompactView (bool visible)
+MainWindow::setCompactView (bool visible)
{
myPrefs.set (Prefs::COMPACT_VIEW, visible);
}
void
-TrMainWindow::toggleSpeedMode ()
+MainWindow::toggleSpeedMode ()
{
myPrefs.toggleBool (Prefs::ALT_SPEED_LIMIT_ENABLED);
const bool mode = myPrefs.get<bool> (Prefs::ALT_SPEED_LIMIT_ENABLED);
myAltSpeedAction->setChecked (mode);
}
void
-TrMainWindow::setToolbarVisible (bool visible)
+MainWindow::setToolbarVisible (bool visible)
{
myPrefs.set (Prefs::TOOLBAR, visible);
}
void
-TrMainWindow::setFilterbarVisible (bool visible)
+MainWindow::setFilterbarVisible (bool visible)
{
myPrefs.set (Prefs::FILTERBAR, visible);
}
void
-TrMainWindow::setStatusbarVisible (bool visible)
+MainWindow::setStatusbarVisible (bool visible)
{
myPrefs.set (Prefs::STATUSBAR, visible);
}
**/
void
-TrMainWindow::toggleWindows (bool doShow)
+MainWindow::toggleWindows (bool doShow)
{
if (!doShow)
{
}
void
-TrMainWindow::trayActivated (QSystemTrayIcon::ActivationReason reason)
+MainWindow::trayActivated (QSystemTrayIcon::ActivationReason reason)
{
if ((reason == QSystemTrayIcon::Trigger) ||
(reason == QSystemTrayIcon::DoubleClick))
void
-TrMainWindow::refreshPref (int key)
+MainWindow::refreshPref (int key)
{
bool b;
int i;
}
void
-TrMainWindow::newTorrent ()
+MainWindow::newTorrent ()
{
MakeDialog * dialog = new MakeDialog (mySession, this);
dialog->setAttribute (Qt::WA_DeleteOnClose);
}
void
-TrMainWindow::openTorrent ()
+MainWindow::openTorrent ()
{
QFileDialog * d;
d = new QFileDialog (this,
}
void
-TrMainWindow::openURL ()
+MainWindow::openURL ()
{
QString str = qApp->clipboard ()->text (QClipboard::Selection);
}
void
-TrMainWindow::addTorrents (const QStringList& filenames)
+MainWindow::addTorrents (const QStringList& filenames)
{
bool showOptions = myPrefs.getBool (Prefs::OPTIONS_PROMPT);
}
void
-TrMainWindow::addTorrent (const AddData& addMe, bool showOptions)
+MainWindow::addTorrent (const AddData& addMe, bool showOptions)
{
if (showOptions)
{
}
void
-TrMainWindow::removeTorrents (const bool deleteFiles)
+MainWindow::removeTorrents (const bool deleteFiles)
{
QSet<int> ids;
QMessageBox msgBox (this);
***/
void
-TrMainWindow::updateNetworkIcon ()
+MainWindow::updateNetworkIcon ()
{
const time_t now = time (NULL);
const int period = 3;
}
void
-TrMainWindow::onNetworkTimer ()
+MainWindow::onNetworkTimer ()
{
updateNetworkIcon ();
}
void
-TrMainWindow::dataReadProgress ()
+MainWindow::dataReadProgress ()
{
if (!myNetworkError)
myLastReadTime = time (NULL);
}
void
-TrMainWindow::dataSendProgress ()
+MainWindow::dataSendProgress ()
{
myLastSendTime = time (NULL);
}
void
-TrMainWindow::onError (QNetworkReply::NetworkError code)
+MainWindow::onError (QNetworkReply::NetworkError code)
{
const bool hadError = myNetworkError;
const bool haveError = (code != QNetworkReply::NoError)
}
void
-TrMainWindow::errorMessage (const QString& msg)
+MainWindow::errorMessage (const QString& msg)
{
myErrorMessage = msg;
}
void
-TrMainWindow::wrongAuthentication ()
+MainWindow::wrongAuthentication ()
{
mySession.stop ();
mySessionDialog->show ();
***/
void
-TrMainWindow::dragEnterEvent (QDragEnterEvent * event)
+MainWindow::dragEnterEvent (QDragEnterEvent * event)
{
const QMimeData * mime = event->mimeData ();
}
void
-TrMainWindow::dropEvent (QDropEvent * event)
+MainWindow::dropEvent (QDropEvent * event)
{
QStringList list;
***/
void
-TrMainWindow::contextMenuEvent (QContextMenuEvent * event)
+MainWindow::contextMenuEvent (QContextMenuEvent * event)
{
QMenu * menu = new QMenu (this);
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef MAIN_WINDOW_H
-#define MAIN_WINDOW_H
+#ifndef QTR_MAIN_WINDOW_H
+#define QTR_MAIN_WINDOW_H
#include <ctime>
#include <QLineEdit>
#include <QWidgetList>
#include <QNetworkReply>
-extern "C"
-{
- struct tr_variant;
-}
-
-#include "filters.h"
-#include "torrent-filter.h"
-#include "ui_mainwin.h"
+#include "Filters.h"
+#include "TorrentFilter.h"
+#include "ui_MainWindow.h"
class AddData;
class ActionDelegator;
class Prefs;
-class Details;
+class DetailsDialog;
class Session;
class TorrentDelegate;
class TorrentDelegateMin;
class QSortFilterProxyModel;
class Filterbar;
-class TrMainWindow: public QMainWindow
+extern "C"
+{
+ struct tr_variant;
+}
+
+class MainWindow: public QMainWindow
{
Q_OBJECT
QPointer<QDialog> myPrefsDialog;
QDialog * myAboutDialog;
QDialog * myStatsDialog;
- Details * myDetailsDialog;
+ DetailsDialog * myDetailsDialog;
QSystemTrayIcon myTrayIcon;
TorrentFilter myFilterModel;
TorrentDelegate * myTorrentDelegate;
void wrongAuthentication ();
public:
- TrMainWindow (Session&, Prefs&, TorrentModel&, bool minized);
- virtual ~TrMainWindow ();
+ MainWindow (Session&, Prefs&, TorrentModel&, bool minized);
+ virtual ~MainWindow ();
protected:
virtual void contextMenuEvent (QContextMenuEvent *);
virtual void dropEvent (QDropEvent *);
};
-#endif
+#endif // QTR_MAIN_WINDOW_H
<number>3</number>
</property>
<item>
- <widget class="TrIconToolButton" name="optionsButton">
+ <widget class="IconToolButton" name="optionsButton">
<property name="icon">
<iconset resource="application.qrc">
<normaloff>:/icons/utilities.png</normaloff>:/icons/utilities.png</iconset>
<widget class="QLabel" name="statsLabel"/>
</item>
<item>
- <widget class="TrIconToolButton" name="statsModeButton">
+ <widget class="IconToolButton" name="statsModeButton">
<property name="icon">
<iconset resource="application.qrc">
<normaloff>:/icons/ratio.png</normaloff>:/icons/ratio.png</iconset>
</widget>
<customwidgets>
<customwidget>
- <class>TrIconToolButton</class>
+ <class>IconToolButton</class>
<extends>QToolButton</extends>
- <header>tricontoolbutton.h</header>
+ <header>IconToolButton.h</header>
</customwidget>
</customwidgets>
<resources>
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/makemeta.h>
#include <libtransmission/utils.h>
-#include "column-resizer.h"
-#include "formatter.h"
-#include "make-dialog.h"
-#include "session.h"
-#include "utils.h"
+#include "ColumnResizer.h"
+#include "Formatter.h"
+#include "MakeDialog.h"
+#include "Session.h"
+#include "Utils.h"
-#include "ui_make-progress-dialog.h"
+#include "ui_MakeProgressDialog.h"
namespace
{
ui.dialogButtons->button (QDialogButtonBox::Open)->setEnabled (b.isDone && b.result == TR_MAKEMETA_OK);
}
-#include "make-dialog.moc"
+#include "MakeDialog.moc"
/***
****
{
ui.setupUi (this);
- ui.destinationButton->setMode (TrPathButton::DirectoryMode);
+ ui.destinationButton->setMode (PathButton::DirectoryMode);
ui.destinationButton->setPath (QDir::homePath ());
- ui.sourceFolderButton->setMode (TrPathButton::DirectoryMode);
- ui.sourceFileButton->setMode (TrPathButton::FileMode);
+ ui.sourceFolderButton->setMode (PathButton::DirectoryMode);
+ ui.sourceFileButton->setMode (PathButton::FileMode);
ColumnResizer * cr (new ColumnResizer (this));
cr->addLayout (ui.filesSectionLayout);
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef MAKE_DIALOG_H
-#define MAKE_DIALOG_H
+#ifndef QTR_MAKE_DIALOG_H
+#define QTR_MAKE_DIALOG_H
#include <memory>
#include <QDialog>
-#include "ui_make-dialog.h"
+#include "ui_MakeDialog.h"
class QAbstractButton;
virtual ~MakeDialog ();
};
-#endif
+#endif // QTR_MAKE_DIALOG_H
</widget>
</item>
<item row="0" column="1">
- <widget class="TrPathButton" name="destinationButton"/>
+ <widget class="PathButton" name="destinationButton"/>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="sourceFolderRadio">
</widget>
</item>
<item row="1" column="1">
- <widget class="TrPathButton" name="sourceFolderButton">
+ <widget class="PathButton" name="sourceFolderButton">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="1">
- <widget class="TrPathButton" name="sourceFileButton"/>
+ <widget class="PathButton" name="sourceFileButton"/>
</item>
<item row="3" column="1">
<widget class="QLabel" name="sourceSizeLabel">
</widget>
<customwidgets>
<customwidget>
- <class>TrPathButton</class>
+ <class>PathButton</class>
<extends>QToolButton</extends>
- <header>path-button.h</header>
+ <header>PathButton.h</header>
</customwidget>
</customwidgets>
<resources/>
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/utils.h> /* mime64 */
#include <libtransmission/variant.h>
-#include "add-data.h"
-#include "file-tree.h"
-#include "freespace-label.h"
-#include "options.h"
-#include "prefs.h"
-#include "session.h"
-#include "torrent.h"
-#include "utils.h"
+#include "AddData.h"
+#include "FreeSpaceLabel.h"
+#include "OptionsDialog.h"
+#include "Prefs.h"
+#include "Session.h"
+#include "Torrent.h"
+#include "Utils.h"
/***
****
if (myAdd.type == AddData::FILENAME)
{
ui.sourceStack->setCurrentWidget (ui.sourceButton);
- ui.sourceButton->setMode (TrPathButton::FileMode);
+ ui.sourceButton->setMode (PathButton::FileMode);
ui.sourceButton->setTitle (tr ("Open Torrent"));
ui.sourceButton->setNameFilter (tr ("Torrent Files (*.torrent);;All Files (*.*)"));
ui.sourceButton->setPath (myAdd.filename);
if (session.isLocal ())
{
ui.destinationStack->setCurrentWidget (ui.destinationButton);
- ui.destinationButton->setMode (TrPathButton::DirectoryMode);
+ ui.destinationButton->setMode (PathButton::DirectoryMode);
ui.destinationButton->setTitle (tr ("Select Destination"));
ui.destinationButton->setPath (downloadDir);
myLocalDestination = downloadDir;
for (tr_file_index_t i = 0; i < myInfo.fileCount; ++i)
{
- TrFile file;
+ TorrentFile file;
file.index = i;
file.priority = myPriorities[i];
file.wanted = myWanted[i];
myVerifyPiecePos = 0;
myVerifyTimer.stop ();
- for (TrFile& f: myFiles)
+ for (TorrentFile& f: myFiles)
f.have = 0;
ui.filesView->update (myFiles);
{
for (auto i = myVerifyBins.begin (), end = myVerifyBins.end (); i != end; ++i)
{
- TrFile& f (myFiles[i.key ()]);
+ TorrentFile& f (myFiles[i.key ()]);
f.have += i.value ();
changedFiles.append (f);
}
if (done)
{
uint64_t have = 0;
- for (const TrFile& f: myFiles)
+ for (const TorrentFile& f: myFiles)
have += f.have;
if (!have) // everything failed
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef OPTIONS_DIALOG_H
-#define OPTIONS_DIALOG_H
+#ifndef QTR_OPTIONS_DIALOG_H
+#define QTR_OPTIONS_DIALOG_H
#include <QCryptographicHash>
#include <QDialog>
#include <QTimer>
#include <QVector>
-#include "add-data.h" // AddData
-#include "file-tree.h" // FileList
+#include "AddData.h" // AddData
+#include "Torrent.h" // FileList
-#include "ui_options.h"
+#include "ui_OptionsDialog.h"
class Prefs;
class Session;
QTimer myEditTimer;
};
-#endif
+#endif // QTR_OPTIONS_DIALOG_H
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <widget class="TrPathButton" name="sourceButton"/>
+ <widget class="PathButton" name="sourceButton"/>
<widget class="QLineEdit" name="sourceEdit"/>
</widget>
</item>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <widget class="TrPathButton" name="destinationButton"/>
+ <widget class="PathButton" name="destinationButton"/>
<widget class="QLineEdit" name="destinationEdit"/>
</widget>
</item>
<item row="2" column="1">
- <widget class="FreespaceLabel" name="freeSpaceLabel">
+ <widget class="FreeSpaceLabel" name="freeSpaceLabel">
<property name="text">
<string notr="true">...</string>
</property>
<customwidget>
<class>FileTreeView</class>
<extends>QTreeView</extends>
- <header>file-tree.h</header>
+ <header>FileTreeView.h</header>
</customwidget>
<customwidget>
- <class>FreespaceLabel</class>
+ <class>FreeSpaceLabel</class>
<extends>QLabel</extends>
- <header>freespace-label.h</header>
+ <header>FreeSpaceLabel.h</header>
</customwidget>
<customwidget>
- <class>TrPathButton</class>
+ <class>PathButton</class>
<extends>QToolButton</extends>
- <header>path-button.h</header>
+ <header>PathButton.h</header>
</customwidget>
</customwidgets>
<resources/>
/*
- * This file Copyright (C) 2014 Mnemosyne LLC
+ * This file Copyright (C) 2014-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QStyleOptionToolButton>
#include <QStylePainter>
-#include "path-button.h"
-#include "utils.h"
+#include "PathButton.h"
+#include "Utils.h"
-TrPathButton::TrPathButton (QWidget * parent):
+PathButton::PathButton (QWidget * parent):
QToolButton (parent),
myMode (DirectoryMode),
myTitle (),
}
void
-TrPathButton::setMode (Mode mode)
+PathButton::setMode (Mode mode)
{
if (myMode == mode)
return;
}
void
-TrPathButton::setTitle (const QString& title)
+PathButton::setTitle (const QString& title)
{
myTitle = title;
}
void
-TrPathButton::setNameFilter (const QString& nameFilter)
+PathButton::setNameFilter (const QString& nameFilter)
{
myNameFilter = nameFilter;
}
void
-TrPathButton::setPath (const QString& path)
+PathButton::setPath (const QString& path)
{
if (myPath == path)
return;
}
const QString&
-TrPathButton::path () const
+PathButton::path () const
{
return myPath;
}
QSize
-TrPathButton::sizeHint () const
+PathButton::sizeHint () const
{
const QSize sh (QToolButton::sizeHint ());
return QSize (qMin (sh.width (), 150), sh.height ());
}
void
-TrPathButton::paintEvent (QPaintEvent * /*event*/)
+PathButton::paintEvent (QPaintEvent * /*event*/)
{
QStylePainter painter(this);
QStyleOptionToolButton option;
}
void
-TrPathButton::onClicked ()
+PathButton::onClicked ()
{
QFileDialog * dialog = new QFileDialog (window (), effectiveTitle ());
dialog->setFileMode (isDirMode () ? QFileDialog::Directory : QFileDialog::ExistingFile);
}
void
-TrPathButton::onFileSelected (const QString& path)
+PathButton::onFileSelected (const QString& path)
{
if (!path.isEmpty ())
setPath (path);
}
void
-TrPathButton::updateAppearance ()
+PathButton::updateAppearance ()
{
const QFileInfo pathInfo (myPath);
}
bool
-TrPathButton::isDirMode () const
+PathButton::isDirMode () const
{
return myMode == DirectoryMode;
}
QString
-TrPathButton::effectiveTitle () const
+PathButton::effectiveTitle () const
{
if (!myTitle.isEmpty ())
return myTitle;
/*
- * This file Copyright (C) 2014 Mnemosyne LLC
+ * This file Copyright (C) 2014-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QToolButton>
-class TrPathButton: public QToolButton
+class PathButton: public QToolButton
{
Q_OBJECT
};
public:
- TrPathButton (QWidget * parent = nullptr);
+ PathButton (QWidget * parent = nullptr);
void setMode (Mode mode);
void setTitle (const QString& title);
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
+#include <stdlib.h>
+
#include <cassert>
#include <iostream>
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h>
#include <libtransmission/variant.h>
-#include <stdlib.h>
-#include "prefs.h"
-#include "types.h"
-#include "utils.h"
+
+#include "CustomVariantType.h"
+#include "Prefs.h"
+#include "Utils.h"
/***
****
{ SHOW_NOTIFICATION_ON_ADD, TR_KEY_torrent_added_notification_enabled, QVariant::Bool },
{ SHOW_NOTIFICATION_ON_COMPLETE, TR_KEY_torrent_complete_notification_enabled, QVariant::Bool },
{ ASKQUIT, TR_KEY_prompt_before_exit, QVariant::Bool },
- { SORT_MODE, TR_KEY_sort_mode, TrTypes::SortModeType },
+ { SORT_MODE, TR_KEY_sort_mode, CustomVariantType::SortModeType },
{ SORT_REVERSED, TR_KEY_sort_reversed, QVariant::Bool },
{ COMPACT_VIEW, TR_KEY_compact_view, QVariant::Bool },
{ FILTERBAR, TR_KEY_show_filterbar, QVariant::Bool },
{ MAIN_WINDOW_WIDTH, TR_KEY_main_window_width, QVariant::Int },
{ MAIN_WINDOW_X, TR_KEY_main_window_x, QVariant::Int },
{ MAIN_WINDOW_Y, TR_KEY_main_window_y, QVariant::Int },
- { FILTER_MODE, TR_KEY_filter_mode, TrTypes::FilterModeType },
+ { FILTER_MODE, TR_KEY_filter_mode, CustomVariantType::FilterModeType },
{ FILTER_TRACKERS, TR_KEY_filter_trackers, QVariant::String },
{ FILTER_TEXT, TR_KEY_filter_text, QVariant::String },
{ SESSION_IS_REMOTE, TR_KEY_remote_session_enabled, QVariant::Bool },
myValues[i].setValue (static_cast<qlonglong> (intVal));
break;
- case TrTypes::SortModeType:
+ case CustomVariantType::SortModeType:
if (tr_variantGetStr (b, &str, NULL))
myValues[i] = QVariant::fromValue (SortMode (QString::fromUtf8 (str)));
break;
- case TrTypes::FilterModeType:
+ case CustomVariantType::FilterModeType:
if (tr_variantGetStr (b, &str, NULL))
myValues[i] = QVariant::fromValue (FilterMode (QString::fromUtf8 (str)));
break;
tr_variantDictAddInt (¤t_settings, key, val.toInt());
break;
- case TrTypes::SortModeType:
+ case CustomVariantType::SortModeType:
tr_variantDictAddStr (¤t_settings, key, val.value<SortMode>().name().toUtf8().constData());
break;
- case TrTypes::FilterModeType:
+ case CustomVariantType::FilterModeType:
tr_variantDictAddStr (¤t_settings, key, val.value<FilterMode>().name().toUtf8().constData());
break;
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QString>
#include <QVariant>
-#include "filters.h"
-
#include <libtransmission/quark.h>
+#include "Filters.h"
+
extern "C"
{
struct tr_variant;
void changed (int key);
};
-#endif
+#endif // QTR_PREFS_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QTimer>
#include <QVBoxLayout>
-#include "column-resizer.h"
-#include "freespace-label.h"
-#include "formatter.h"
-#include "hig.h"
-#include "prefs.h"
-#include "prefs-dialog.h"
-#include "session.h"
-#include "utils.h"
+#include "ColumnResizer.h"
+#include "FreeSpaceLabel.h"
+#include "Formatter.h"
+#include "Prefs.h"
+#include "PrefsDialog.h"
+#include "Session.h"
+#include "Utils.h"
/***
****
w->setTime (QTime (0, 0).addSecs (myPrefs.getInt(prefKey) * 60));
else if (auto w = qobject_cast<QLineEdit*> (widget))
w->setText (myPrefs.getString (prefKey));
- else if (auto w = qobject_cast<TrPathButton*> (widget))
+ else if (auto w = qobject_cast<PathButton*> (widget))
w->setPath (myPrefs.getString (prefKey));
else
return false;
connect (widget, SIGNAL (editingFinished ()), SLOT (timeEditingFinished ()));
else if (widget->inherits ("QLineEdit"))
connect (widget, SIGNAL (editingFinished ()), SLOT (lineEditingFinished ()));
- else if (widget->inherits ("TrPathButton"))
+ else if (widget->inherits ("PathButton"))
connect (widget, SIGNAL (pathChanged (QString)), SLOT (pathChanged (QString)));
else if (widget->inherits ("QAbstractSpinBox"))
connect (widget, SIGNAL (editingFinished ()), SLOT (spinBoxEditingFinished ()));
void
PrefsDialog::pathChanged (const QString& path)
{
- if (auto b = qobject_cast<const TrPathButton*> (sender ()))
+ if (auto b = qobject_cast<const PathButton*> (sender ()))
setPref(getPrefKey (b), path);
}
ui.incompleteDirStack->setCurrentWidget (ui.incompleteDirButton);
ui.completionScriptStack->setCurrentWidget (ui.completionScriptButton);
- ui.watchDirButton->setMode (TrPathButton::DirectoryMode);
- ui.downloadDirButton->setMode (TrPathButton::DirectoryMode);
- ui.incompleteDirButton->setMode (TrPathButton::DirectoryMode);
- ui.completionScriptButton->setMode (TrPathButton::FileMode);
+ ui.watchDirButton->setMode (PathButton::DirectoryMode);
+ ui.downloadDirButton->setMode (PathButton::DirectoryMode);
+ ui.incompleteDirButton->setMode (PathButton::DirectoryMode);
+ ui.completionScriptButton->setMode (PathButton::FileMode);
ui.watchDirButton->setTitle (tr ("Select Watch Directory"));
ui.downloadDirButton->setTitle (tr ("Select Destination"));
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef PREFS_DIALOG_H
-#define PREFS_DIALOG_H
+#ifndef QTR_PREFS_DIALOG_H
+#define QTR_PREFS_DIALOG_H
#include <QDialog>
#include <QMap>
#include <QSet>
-#include "prefs.h"
-#include "ui_prefs-dialog.h"
+#include "Prefs.h"
+#include "ui_PrefsDialog.h"
class QAbstractButton;
class QCheckBox;
class QVBoxLayout;
class QWidget;
-class FreespaceLabel;
+class FreeSpaceLabel;
class Prefs;
class Session;
QMessageBox * myBlocklistDialog;
};
-#endif
+#endif // QTR_PREFS_DIALOG_H
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <widget class="TrPathButton" name="watchDirButton"/>
+ <widget class="PathButton" name="watchDirButton"/>
<widget class="QLineEdit" name="watchDirEdit"/>
</widget>
</item>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <widget class="TrPathButton" name="downloadDirButton"/>
+ <widget class="PathButton" name="downloadDirButton"/>
<widget class="QLineEdit" name="downloadDirEdit"/>
</widget>
</item>
<item row="5" column="1">
- <widget class="FreespaceLabel" name="downloadDirFreeSpaceLabel">
+ <widget class="FreeSpaceLabel" name="downloadDirFreeSpaceLabel">
<property name="text">
<string notr="true">...</string>
</property>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <widget class="TrPathButton" name="incompleteDirButton"/>
+ <widget class="PathButton" name="incompleteDirButton"/>
<widget class="QLineEdit" name="incompleteDirEdit"/>
</widget>
</item>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <widget class="TrPathButton" name="completionScriptButton"/>
+ <widget class="PathButton" name="completionScriptButton"/>
<widget class="QLineEdit" name="completionScriptEdit"/>
</widget>
</item>
</widget>
<customwidgets>
<customwidget>
- <class>TrPathButton</class>
+ <class>PathButton</class>
<extends>QToolButton</extends>
- <header>path-button.h</header>
+ <header>PathButton.h</header>
</customwidget>
<customwidget>
- <class>FreespaceLabel</class>
+ <class>FreeSpaceLabel</class>
<extends>QLabel</extends>
- <header>freespace-label.h</header>
+ <header>FreeSpaceLabel.h</header>
</customwidget>
</customwidgets>
<resources>
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QDir>
-#include "relocate.h"
-#include "session.h"
-#include "torrent.h"
-#include "torrent-model.h"
+#include "RelocateDialog.h"
+#include "Session.h"
+#include "Torrent.h"
+#include "TorrentModel.h"
bool RelocateDialog::myMoveFlag = true;
if (mySession.isServer ())
{
ui.newLocationStack->setCurrentWidget (ui.newLocationButton);
- ui.newLocationButton->setMode (TrPathButton::DirectoryMode);
+ ui.newLocationButton->setMode (PathButton::DirectoryMode);
ui.newLocationButton->setTitle (tr ("Select Location"));
ui.newLocationButton->setPath (path);
}
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef RELOCATE_DIALOG_H
-#define RELOCATE_DIALOG_H
+#ifndef QTR_RELOCATE_DIALOG_H
+#define QTR_RELOCATE_DIALOG_H
#include <QDialog>
#include <QSet>
-#include "ui_relocate.h"
+#include "ui_RelocateDialog.h"
class Session;
class TorrentModel;
static bool myMoveFlag;
};
-#endif
+#endif // QTR_RELOCATE_DIALOG_H
</item>
<item row="0" column="1">
<widget class="QStackedWidget" name="newLocationStack">
- <widget class="TrPathButton" name="newLocationButton"/>
+ <widget class="PathButton" name="newLocationButton"/>
<widget class="QLineEdit" name="newLocationEdit"/>
</widget>
</item>
</widget>
<customwidgets>
<customwidget>
- <class>TrPathButton</class>
+ <class>PathButton</class>
<extends>QToolButton</extends>
- <header>path-button.h</header>
+ <header>PathButton.h</header>
</customwidget>
</customwidgets>
<resources/>
/*
- * This file Copyright (C) 2014 Mnemosyne LLC
+ * This file Copyright (C) 2014-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/utils.h> // tr_free
#include <libtransmission/version.h> // LONG_VERSION_STRING
-#include "rpc-client.h"
+#include "RpcClient.h"
// #define DEBUG_HTTP
/*
- * This file Copyright (C) 2014 Mnemosyne LLC
+ * This file Copyright (C) 2014-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef TR_RPC_CLIENT_H
-#define TR_RPC_CLIENT_H
+#ifndef QTR_RPC_CLIENT_H
+#define QTR_RPC_CLIENT_H
#include <QNetworkReply>
#include <QObject>
QNetworkAccessManager * myNAM;
};
-#endif
+#endif // QTR_RPC_CLIENT_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/utils.h> // tr_free
#include <libtransmission/variant.h>
-#include "add-data.h"
-#include "prefs.h"
-#include "session.h"
-#include "session-dialog.h"
-#include "torrent.h"
-#include "utils.h"
+#include "AddData.h"
+#include "Prefs.h"
+#include "Session.h"
+#include "SessionDialog.h"
+#include "Torrent.h"
+#include "Utils.h"
namespace
{
myPrefs.set (i, val);
break;
}
- case TrTypes::FilterModeType:
- case TrTypes::SortModeType:
+ case CustomVariantType::FilterModeType:
+ case CustomVariantType::SortModeType:
case QVariant::String:
{
const char * val;
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef TR_APP_SESSION_H
-#define TR_APP_SESSION_H
+#ifndef QTR_SESSION_H
+#define QTR_SESSION_H
#include <QObject>
#include <QSet>
#include <libtransmission/transmission.h>
#include <libtransmission/quark.h>
-#include "rpc-client.h"
+#include "RpcClient.h"
class AddData;
class Prefs;
RpcClient myRpc;
};
-#endif
+#endif // QTR_SESSION_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#include "prefs.h"
-#include "session.h"
-#include "session-dialog.h"
+#include "Prefs.h"
+#include "Session.h"
+#include "SessionDialog.h"
/***
****
/*
- * This file Copyright (C) 2010-2014 Mnemosyne LLC
+ * This file Copyright (C) 2010-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef SESSION_DIALOG_H
-#define SESSION_DIALOG_H
+#ifndef QTR_SESSION_DIALOG_H
+#define QTR_SESSION_DIALOG_H
#include <QDialog>
#include <QWidgetList>
-#include "ui_session-dialog.h"
+#include "ui_SessionDialog.h"
class Prefs;
class Session;
QWidgetList myAuthWidgets;
};
-#endif
+#endif // QTR_SESSION_DIALOG_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#ifndef QTR_SPEED_H
#define QTR_SPEED_H
-#include "formatter.h"
+#include "Formatter.h"
class Speed
{
bool operator< (const Speed& that) const { return _Bps < that._Bps; }
};
-#endif
+#endif // QTR_SPEED_H
#include <QStyle>
#include <QStyleOption>
-#include "squeezelabel.h"
+#include "SqueezeLabel.h"
SqueezeLabel::SqueezeLabel (const QString& text, QWidget * parent):
QLabel (text, parent)
**
****************************************************************************/
-#ifndef SQUEEZELABEL_H
-#define SQUEEZELABEL_H
+#ifndef QTR_SQUEEZE_LABEL_H
+#define QTR_SQUEEZE_LABEL_H
#include <QLabel>
-class SqueezeLabel : public QLabel
+class SqueezeLabel: public QLabel
{
Q_OBJECT
void paintEvent (QPaintEvent* paintEvent);
};
-#endif // SQUEEZELABEL_H
-
+#endif // QTR_SQUEEZE_LABEL_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QTimer>
-#include "column-resizer.h"
-#include "formatter.h"
-#include "session.h"
-#include "stats-dialog.h"
+#include "ColumnResizer.h"
+#include "Formatter.h"
+#include "Session.h"
+#include "StatsDialog.h"
enum
{
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef STATS_DIALOG_H
-#define STATS_DIALOG_H
+#ifndef QTR_STATS_DIALOG_H
+#define QTR_STATS_DIALOG_H
#include <QDialog>
-#include "ui_stats-dialog.h"
+#include "ui_StatsDialog.h"
class Session;
class QTimer;
Ui::StatsDialog ui;
};
-#endif
+#endif // QTR_STATS_DIALOG_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/utils.h> /* tr_new0, tr_strdup */
#include <libtransmission/variant.h>
-#include "app.h"
-#include "prefs.h"
-#include "torrent.h"
-#include "utils.h"
-
+#include "Application.h"
+#include "Prefs.h"
+#include "Torrent.h"
+#include "Utils.h"
Torrent::Torrent (const Prefs& prefs, int id):
magnetTorrent (false),
{ FAILED_EVER, TR_KEY_corruptEver, QVariant::ULongLong, STAT_EXTRA },
{ TRACKERS, TR_KEY_trackers, QVariant::StringList, STAT },
{ HOSTS, TR_KEY_NONE, QVariant::StringList, DERIVED },
- { TRACKERSTATS, TR_KEY_trackerStats, TrTypes::TrackerStatsList, STAT_EXTRA },
+ { TRACKERSTATS, TR_KEY_trackerStats, CustomVariantType::TrackerStatsList, STAT_EXTRA },
{ MIME_ICON, TR_KEY_NONE, QVariant::Icon, DERIVED },
{ SEED_RATIO_LIMIT, TR_KEY_seedRatioLimit, QVariant::Double, STAT },
{ SEED_RATIO_MODE, TR_KEY_seedRatioMode, QVariant::Int, STAT },
{ COMMENT, TR_KEY_comment, QVariant::String, INFO },
{ CREATOR, TR_KEY_creator, QVariant::String, INFO },
{ MANUAL_ANNOUNCE_TIME, TR_KEY_manualAnnounceTime, QVariant::DateTime, STAT_EXTRA },
- { PEERS, TR_KEY_peers, TrTypes::PeerList, STAT_EXTRA },
+ { PEERS, TR_KEY_peers, CustomVariantType::PeerList, STAT_EXTRA },
{ BANDWIDTH_PRIORITY, TR_KEY_bandwidthPriority, QVariant::Int, STAT_EXTRA },
{ QUEUE_POSITION, TR_KEY_queuePosition, QVariant::Int, STAT },
};
bool
Torrent::hasFileSubstring (const QString& substr) const
{
- for (const TrFile& file: myFiles)
+ for (const TorrentFile& file: myFiles)
if (file.filename.contains (substr, Qt::CaseInsensitive))
return true;
}
case QVariant::StringList:
- case TrTypes::PeerList:
+ case CustomVariantType::PeerList:
// handled below
break;
while ((child = tr_variantListChild (files, i)))
{
- TrFile file;
+ TorrentFile file;
size_t len;
file.index = i++;
int64_t intVal;
bool boolVal;
tr_variant * child = tr_variantListChild (files, i);
- TrFile& file (myFiles[i]);
+ TorrentFile& file (myFiles[i]);
if (tr_variantDictFindInt (child, TR_KEY_bytesCompleted, &intVal))
file.have = intVal;
QStringList hosts;
for (const QString& tracker: list)
{
- const QString host = Favicons::getHost (QUrl (tracker));
+ const QString host = FaviconCache::getHost (QUrl (tracker));
if (!host.isEmpty())
hosts.append (host);
}
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/transmission.h>
#include <libtransmission/quark.h>
-#include "speed.h"
-#include "types.h"
+#include "CustomVariantType.h"
+#include "Speed.h"
#ifdef ERROR
#undef ERROR
#endif
+class Prefs;
+class QPixmap;
+class QStyle;
+
extern "C"
{
struct tr_variant;
}
-class Prefs;
-class QPixmap;
-class QStyle;
-
struct Peer
{
bool clientIsChoked;
Q_DECLARE_METATYPE(TrackerStat)
Q_DECLARE_METATYPE(TrackerStatsList)
-struct TrFile
+struct TorrentFile
{
- TrFile(): wanted(true), index(-1), priority(0), size(0), have(0) {}
+ TorrentFile(): wanted(true), index(-1), priority(0), size(0), have(0) {}
bool wanted;
int index;
uint64_t have;
};
-typedef QList<TrFile> FileList;
-Q_DECLARE_METATYPE(TrFile)
+typedef QList<TorrentFile> FileList;
+Q_DECLARE_METATYPE(TorrentFile)
Q_DECLARE_METATYPE(FileList)
Q_DECLARE_METATYPE(const Torrent*)
-#endif
-
+#endif // QTR_TORRENT_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QPixmapCache>
#include <QStyleOptionProgressBar>
-#include "formatter.h"
-#include "torrent.h"
-#include "torrent-delegate.h"
-#include "torrent-model.h"
-#include "utils.h"
+#include "Formatter.h"
+#include "Torrent.h"
+#include "TorrentDelegate.h"
+#include "TorrentModel.h"
+#include "Utils.h"
enum
{
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
};
-#endif
+#endif // QTR_TORRENT_DELEGATE_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h>
-#include "torrent.h"
-#include "torrent-delegate-min.h"
-#include "torrent-model.h"
-#include "utils.h"
+#include "Torrent.h"
+#include "TorrentDelegateMin.h"
+#include "TorrentModel.h"
+#include "Utils.h"
enum
{
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#define QTR_TORRENT_DELEGATE_MIN_H
#include <QSize>
-#include "torrent-delegate.h"
+
+#include "TorrentDelegate.h"
class QStyleOptionViewItem;
class QStyle;
virtual ~TorrentDelegateMin () {}
};
-#endif
+#endif // QTR_TORRENT_DELEGATE_MIN_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <algorithm>
#include <iostream>
-#include "filters.h"
-#include "hig.h"
-#include "prefs.h"
-#include "torrent.h"
-#include "torrent-filter.h"
-#include "torrent-model.h"
-#include "utils.h"
+#include "Filters.h"
+#include "Prefs.h"
+#include "Torrent.h"
+#include "TorrentFilter.h"
+#include "TorrentModel.h"
+#include "Utils.h"
TorrentFilter::TorrentFilter (const Prefs& prefs):
myPrefs (prefs)
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
const Prefs& myPrefs;
};
-#endif
+#endif // QTR_TORRENT_FILTER_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/transmission.h>
#include <libtransmission/variant.h>
-#include "torrent-delegate.h"
-#include "torrent-model.h"
+#include "TorrentDelegate.h"
+#include "TorrentModel.h"
void
TorrentModel::clear ()
/*
- * This file Copyright (C) 2010-2014 Mnemosyne LLC
+ * This file Copyright (C) 2010-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QSet>
#include <QVector>
-#include "speed.h"
-#include "torrent.h"
+#include "Speed.h"
+#include "Torrent.h"
class Prefs;
virtual ~TorrentModel ();
};
-#endif
+#endif // QTR_TORRENT_MODEL_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h>
-#include "favicon.h"
-#include "formatter.h"
-#include "torrent.h"
-#include "tracker-delegate.h"
-#include "tracker-model.h"
-#include "utils.h"
+#include "FaviconCache.h"
+#include "Formatter.h"
+#include "Torrent.h"
+#include "TrackerDelegate.h"
+#include "TrackerModel.h"
+#include "Utils.h"
/***
****
const QPoint& topLeft, int width)
{
const QStyle * style (qApp->style ());
- const QSize iconSize = Favicons::getIconSize ();
+ const QSize iconSize = FaviconCache::getIconSize ();
QRect baseRect (topLeft, QSize (width, 0));
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
class QPainter;
class QStyleOptionViewItem;
class QStyle;
+
class Session;
struct TrackerInfo;
bool myShowMore;
};
-#endif
+#endif // QTR_TRACKER_DELEGATE_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QUrl>
-#include "app.h" // MyApp
-#include "tracker-model.h"
+#include "Application.h" // Application
+#include "TrackerModel.h"
int
TrackerModel::rowCount (const QModelIndex& parent) const
/*
- * This file Copyright (C) 2010-2014 Mnemosyne LLC
+ * This file Copyright (C) 2010-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <QSet>
#include <QVector>
-#include "torrent.h"
-#include "torrent-model.h"
+#include "Torrent.h"
+#include "TorrentModel.h"
struct TrackerInfo
{
virtual ~TrackerModel () {}
};
-#endif
+#endif // QTR_TRACKER_MODEL_H
/*
- * This file Copyright (C) 2010-2014 Mnemosyne LLC
+ * This file Copyright (C) 2010-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#include "tracker-model.h"
-#include "tracker-model-filter.h"
+#include "TrackerModel.h"
+#include "TrackerModelFilter.h"
TrackerModelFilter::TrackerModelFilter (QObject * parent):
QSortFilterProxyModel (parent),
/*
- * This file Copyright (C) 2010-2014 Mnemosyne LLC
+ * This file Copyright (C) 2010-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
bool myShowBackups;
};
-#endif
+#endif // QTR_TRACKER_MODEL_FILTER_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#endif
#include <QApplication>
+#include <QColor>
#include <QDataStream>
#include <QFile>
#include <QFileDialog>
#include <libtransmission/transmission.h>
#include <libtransmission/utils.h> // tr_formatter
-#include "utils.h"
+#include "Utils.h"
/***
****
const QFileInfo pathInfo (path);
return pathInfo.fileName ().isEmpty () ? pathInfo.absolutePath () : pathInfo.absoluteFilePath ();
}
+
+QColor
+Utils::getFadedColor (const QColor& color)
+{
+ QColor fadedColor (color);
+ fadedColor.setAlpha (128);
+ return fadedColor;
+}
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef QTR_UTILS
-#define QTR_UTILS
+#ifndef QTR_UTILS_H
+#define QTR_UTILS_H
+
+#include <cctype> // isxdigit()
#include <QIcon>
#include <QObject>
#include <QRect>
#include <QString>
-#include <cctype> // isxdigit()
+#include "Speed.h"
-#include "speed.h"
+class QColor;
class Utils: public QObject
{
rect.adjust (dx1, 0, -dx2, 0);
}
+ static QColor getFadedColor (const QColor& color);
+
///
/// URLs
///
}
};
-#endif
+#endif // QTR_UTILS_H
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
#include <libtransmission/transmission.h>
-#include "prefs.h"
-#include "torrent-model.h"
-#include "watchdir.h"
+#include "Prefs.h"
+#include "TorrentModel.h"
+#include "WatchDir.h"
/***
****
/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
+ * This file Copyright (C) 2009-2015 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
* $Id$
*/
-#ifndef QTR_WATCHDIR_H
-#define QTR_WATCHDIR_H
+#ifndef QTR_WATCH_DIR_H
+#define QTR_WATCH_DIR_H
#include <QObject>
#include <QSet>
#include <QString>
-class TorrentModel;
class QFileSystemWatcher;
+class TorrentModel;
+
class WatchDir: public QObject
{
Q_OBJECT
QFileSystemWatcher * myWatcher;
};
-#endif
+#endif // QTR_WATCH_DIR_H
+++ /dev/null
-/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
- *
- * It may be used under the GNU GPL versions 2 or 3
- * or any future license endorsed by Mnemosyne LLC.
- *
- * $Id$
- */
-
-#include <algorithm>
-#include <cassert>
-
-#include <QApplication>
-#include <QHeaderView>
-#include <QPainter>
-#include <QResizeEvent>
-#include <QSortFilterProxyModel>
-#include <QStringList>
-
-#include <libtransmission/transmission.h> // priorities
-
-#include "file-tree.h"
-#include "formatter.h"
-#include "hig.h"
-#include "torrent.h" // FileList
-#include "utils.h" // mime icons
-
-enum
-{
- COL_NAME,
- FIRST_VISIBLE_COLUMN = COL_NAME,
- COL_SIZE,
- COL_PROGRESS,
- COL_WANTED,
- COL_PRIORITY,
- LAST_VISIBLE_COLUMN = COL_PRIORITY,
-
- COL_FILE_INDEX,
- NUM_COLUMNS
-};
-
-/****
-*****
-****/
-
-const QHash<QString,int>&
-FileTreeItem::getMyChildRows ()
-{
- const size_t n = childCount();
-
- // ensure that all the rows are hashed
- while (myFirstUnhashedRow < n)
- {
- myChildRows.insert (myChildren[myFirstUnhashedRow]->name(),
- myFirstUnhashedRow);
- ++myFirstUnhashedRow;
- }
-
- return myChildRows;
-}
-
-
-FileTreeItem::~FileTreeItem ()
-{
- assert(myChildren.isEmpty());
-
- if (myParent != 0)
- {
- const int pos = row();
- assert ((pos>=0) && "couldn't find child in parent's lookup");
- myParent->myChildren.removeAt(pos);
- myParent->myChildRows.remove(name());
- myParent->myFirstUnhashedRow = pos;
- }
-}
-
-void
-FileTreeItem::appendChild (FileTreeItem * child)
-{
- const size_t n = childCount();
- child->myParent = this;
- myChildren.append (child);
- myFirstUnhashedRow = n;
-}
-
-FileTreeItem *
-FileTreeItem::child (const QString& filename)
-{
- FileTreeItem * item(0);
-
- const int row = getMyChildRows().value (filename, -1);
- if (row != -1)
- {
- item = child (row);
- assert (filename == item->name());
- }
-
- return item;
-}
-
-int
-FileTreeItem::row () const
-{
- int i(-1);
-
- if(myParent)
- {
- i = myParent->getMyChildRows().value (name(), -1);
- assert (this == myParent->myChildren[i]);
- }
-
- return i;
-}
-
-QVariant
-FileTreeItem::data (int column, int role) const
-{
- QVariant value;
-
- if (column == COL_FILE_INDEX)
- {
- value.setValue (myFileIndex);
- }
- else if (role == Qt::EditRole)
- {
- if (column == 0)
- value.setValue (name());
- }
- else if ((role == Qt::TextAlignmentRole) && column == COL_SIZE)
- {
- value = Qt::AlignRight + Qt::AlignVCenter;
- }
- else if (role == Qt::DisplayRole)
- {
- switch(column)
- {
- case COL_NAME:
- value.setValue (name());
- break;
-
- case COL_SIZE:
- value.setValue (sizeString() + QLatin1String (" "));
- break;
-
- case COL_PROGRESS:
- value.setValue (progress());
- break;
-
- case COL_WANTED:
- value.setValue (isSubtreeWanted());
- break;
-
- case COL_PRIORITY:
- value.setValue (priorityString());
- break;
- }
- }
- else if (role == Qt::DecorationRole && column == COL_NAME)
- {
- if (childCount () > 0)
- value = qApp->style ()->standardIcon (QStyle::SP_DirOpenIcon);
- else
- value = Utils::guessMimeIcon (name ());
- }
-
- return value;
-}
-
-void
-FileTreeItem::getSubtreeWantedSize (uint64_t& have, uint64_t& total) const
-{
- if (myIsWanted)
- {
- have += myHaveSize;
- total += myTotalSize;
- }
-
- for (const FileTreeItem * const i: myChildren)
- i->getSubtreeWantedSize(have, total);
-}
-
-double
-FileTreeItem::progress () const
-{
- double d(0);
- uint64_t have(0), total(0);
-
- getSubtreeWantedSize (have, total);
- if (total)
- d = have / (double)total;
-
- return d;
-}
-
-QString
-FileTreeItem::sizeString () const
-{
- QString str;
-
- if (myChildren.isEmpty())
- {
- str = Formatter::sizeToString (myTotalSize);
- }
- else
- {
- uint64_t have = 0;
- uint64_t total = 0;
- getSubtreeWantedSize (have, total);
- str = Formatter::sizeToString (total);
- }
-
- return str;
-}
-
-std::pair<int,int>
-FileTreeItem::update (const QString& name,
- bool wanted,
- int priority,
- uint64_t haveSize,
- bool updateFields)
-{
- int changed_count = 0;
- int changed_columns[4];
-
- if (myName != name)
- {
- if (myParent)
- myParent->myFirstUnhashedRow = row();
-
- myName = name;
- changed_columns[changed_count++] = COL_NAME;
- }
-
- if (fileIndex () != -1)
- {
- if (myHaveSize != haveSize)
- {
- myHaveSize = haveSize;
- changed_columns[changed_count++] = COL_PROGRESS;
- }
-
- if (updateFields)
- {
- if (myIsWanted != wanted)
- {
- myIsWanted = wanted;
- changed_columns[changed_count++] = COL_WANTED;
- }
-
- if (myPriority != priority)
- {
- myPriority = priority;
- changed_columns[changed_count++] = COL_PRIORITY;
- }
- }
- }
-
- std::pair<int,int> changed (-1, -1);
- if (changed_count > 0)
- {
- std::sort (changed_columns, changed_columns+changed_count);
- changed.first = changed_columns[0];
- changed.second = changed_columns[changed_count-1];
- }
- return changed;
-}
-
-QString
-FileTreeItem::priorityString () const
-{
- const int i = priority();
-
- switch (i)
- {
- case LOW: return tr("Low");
- case HIGH: return tr("High");
- case NORMAL: return tr("Normal");
- default: return tr("Mixed");
- }
-}
-
-int
-FileTreeItem::priority () const
-{
- int i(0);
-
- if (myChildren.isEmpty())
- {
- switch (myPriority)
- {
- case TR_PRI_LOW:
- i |= LOW;
- break;
-
- case TR_PRI_HIGH:
- i |= HIGH;
- break;
-
- default:
- i |= NORMAL;
- break;
- }
- }
-
- for (const FileTreeItem * const child: myChildren)
- i |= child->priority();
-
- return i;
-}
-
-void
-FileTreeItem::setSubtreePriority (int i, QSet<int>& ids)
-{
- if (myPriority != i)
- {
- myPriority = i;
-
- if (myFileIndex >= 0)
- ids.insert (myFileIndex);
- }
-
- for (FileTreeItem * const child: myChildren)
- child->setSubtreePriority (i, ids);
-}
-
-void
-FileTreeItem::twiddlePriority (QSet<int>& ids, int& p)
-{
- const int old(priority());
-
- if (old & LOW)
- p = TR_PRI_NORMAL;
- else if (old & NORMAL)
- p = TR_PRI_HIGH;
- else
- p = TR_PRI_LOW;
-
- setSubtreePriority (p, ids);
-}
-
-int
-FileTreeItem::isSubtreeWanted () const
-{
- if(myChildren.isEmpty())
- return myIsWanted ? Qt::Checked : Qt::Unchecked;
-
- int wanted(-1);
- for (const FileTreeItem * const child: myChildren)
- {
- const int childWanted = child->isSubtreeWanted();
-
- if (wanted == -1)
- wanted = childWanted;
-
- if (wanted != childWanted)
- wanted = Qt::PartiallyChecked;
-
- if (wanted == Qt::PartiallyChecked)
- return wanted;
- }
-
- return wanted;
-}
-
-void
-FileTreeItem::setSubtreeWanted (bool b, QSet<int>& ids)
-{
- if (myIsWanted != b)
- {
- myIsWanted = b;
-
- if (myFileIndex >= 0)
- ids.insert(myFileIndex);
- }
-
- for (FileTreeItem * const child: myChildren)
- child->setSubtreeWanted (b, ids);
-}
-
-void
-FileTreeItem::twiddleWanted (QSet<int>& ids, bool& wanted)
-{
- wanted = isSubtreeWanted() != Qt::Checked;
- setSubtreeWanted (wanted, ids);
-}
-
-QString
-FileTreeItem::path () const
-{
- QString itemPath;
- const FileTreeItem * item = this;
-
- while (item != NULL && !item->name().isEmpty())
- {
- if (itemPath.isEmpty())
- itemPath = item->name();
- else
- itemPath = item->name() + QLatin1Char ('/') + itemPath;
- item = item->parent ();
- }
-
- return itemPath;
-}
-
-bool
-FileTreeItem::isComplete () const
-{
- return myHaveSize == totalSize ();
-}
-
-/***
-****
-****
-***/
-
-FileTreeModel::FileTreeModel (QObject * parent, bool isEditable):
- QAbstractItemModel(parent),
- myRootItem (new FileTreeItem),
- myIndexCache (),
- myIsEditable (isEditable)
-{
-}
-
-FileTreeModel::~FileTreeModel()
-{
- clear();
-
- delete myRootItem;
-}
-
-void
-FileTreeModel::setEditable (bool editable)
-{
- myIsEditable = editable;
-}
-
-FileTreeItem *
-FileTreeModel::itemFromIndex (const QModelIndex& index) const
-{
- return static_cast<FileTreeItem*>(index.internalPointer());
-}
-
-QVariant
-FileTreeModel::data (const QModelIndex &index, int role) const
-{
- QVariant value;
-
- if (index.isValid())
- value = itemFromIndex(index)->data (index.column(), role);
-
- return value;
-}
-
-Qt::ItemFlags
-FileTreeModel::flags (const QModelIndex& index) const
-{
- int i(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
-
- if(myIsEditable && (index.column() == COL_NAME))
- i |= Qt::ItemIsEditable;
-
- if(index.column() == COL_WANTED)
- i |= Qt::ItemIsUserCheckable | Qt::ItemIsTristate;
-
- return (Qt::ItemFlags)i;
-}
-
-bool
-FileTreeModel::setData (const QModelIndex& index, const QVariant& newname, int role)
-{
- if (role == Qt::EditRole)
- {
- FileTreeItem * item = itemFromIndex (index);
-
- emit pathEdited (item->path (), newname.toString ());
- }
-
- return false; // don't update the view until the session confirms the change
-}
-
-QVariant
-FileTreeModel::headerData (int column, Qt::Orientation orientation, int role) const
-{
- QVariant data;
-
- if (orientation==Qt::Horizontal && role==Qt::DisplayRole)
- {
- switch (column)
- {
- case COL_NAME:
- data.setValue (tr("File"));
- break;
-
- case COL_SIZE:
- data.setValue (tr("Size"));
- break;
-
- case COL_PROGRESS:
- data.setValue (tr("Progress"));
- break;
-
- case COL_WANTED:
- data.setValue (tr("Download"));
- break;
-
- case COL_PRIORITY:
- data.setValue (tr("Priority"));
- break;
-
- default:
- break;
- }
- }
-
- return data;
-}
-
-QModelIndex
-FileTreeModel::index (int row, int column, const QModelIndex& parent) const
-{
- QModelIndex i;
-
- if (hasIndex (row, column, parent))
- {
- FileTreeItem * parentItem;
-
- if (!parent.isValid ())
- parentItem = myRootItem;
- else
- parentItem = itemFromIndex (parent);
-
- FileTreeItem * childItem = parentItem->child (row);
-
- if (childItem)
- i = createIndex (row, column, childItem);
- }
-
- return i;
-}
-
-QModelIndex
-FileTreeModel::parent (const QModelIndex& child) const
-{
- return parent (child, 0); // QAbstractItemModel::parent() wants col 0
-}
-
-QModelIndex
-FileTreeModel::parent (const QModelIndex& child, int column) const
-{
- QModelIndex parent;
-
- if (child.isValid())
- parent = indexOf (itemFromIndex(child)->parent(), column);
-
- return parent;
-}
-
-int
-FileTreeModel::rowCount (const QModelIndex& parent) const
-{
- FileTreeItem * parentItem;
-
- if (parent.isValid())
- parentItem = itemFromIndex (parent);
- else
- parentItem = myRootItem;
-
- return parentItem->childCount();
-}
-
-int
-FileTreeModel::columnCount (const QModelIndex& parent) const
-{
- Q_UNUSED(parent);
-
- return NUM_COLUMNS;
-}
-
-QModelIndex
-FileTreeModel::indexOf (FileTreeItem * item, int column) const
-{
- if (!item || item==myRootItem)
- return QModelIndex();
-
- return createIndex(item->row(), column, item);
-}
-
-void
-FileTreeModel::clearSubtree (const QModelIndex& top)
-{
- size_t i = rowCount (top);
-
- while (i > 0)
- clearSubtree(index(--i, 0, top));
-
- FileTreeItem * const item = itemFromIndex (top);
- if (item == 0)
- return;
-
- if (item->fileIndex () != -1)
- myIndexCache.remove (item->fileIndex ());
-
- delete item;
-}
-
-void
-FileTreeModel::clear ()
-{
- beginResetModel ();
- clearSubtree (QModelIndex());
- endResetModel ();
-
- assert (myIndexCache.isEmpty ());
-}
-
-FileTreeItem *
-FileTreeModel::findItemForFileIndex (int fileIndex) const
-{
- return myIndexCache.value (fileIndex, 0);
-}
-
-void
-FileTreeModel::addFile (int fileIndex,
- const QString & filename,
- bool wanted,
- int priority,
- uint64_t totalSize,
- uint64_t have,
- QList<QModelIndex> & rowsAdded,
- bool updateFields)
-{
- FileTreeItem * item;
- QStringList tokens = filename.split (QChar::fromLatin1('/'));
-
- item = findItemForFileIndex (fileIndex);
-
- if (item) // this file is already in the tree, we've added this
- {
- QModelIndex indexWithChangedParents;
- while (!tokens.isEmpty())
- {
- const QString token = tokens.takeLast();
- const std::pair<int,int> changed = item->update (token, wanted, priority, have, updateFields);
- if (changed.first >= 0)
- {
- dataChanged (indexOf (item, changed.first), indexOf (item, changed.second));
- if (!indexWithChangedParents.isValid () &&
- changed.first <= COL_PRIORITY && changed.second >= COL_SIZE)
- indexWithChangedParents = indexOf (item, 0);
- }
- item = item->parent();
- }
- assert (item == myRootItem);
- if (indexWithChangedParents.isValid ())
- parentsChanged (indexWithChangedParents, COL_SIZE, COL_PRIORITY);
- }
- else // we haven't build the FileTreeItems for these tokens yet
- {
- bool added = false;
-
- item = myRootItem;
- while (!tokens.isEmpty())
- {
- const QString token = tokens.takeFirst();
- FileTreeItem * child(item->child(token));
- if (!child)
- {
- added = true;
- QModelIndex parentIndex (indexOf(item, 0));
- const int n (item->childCount());
-
- beginInsertRows (parentIndex, n, n);
- if (tokens.isEmpty())
- child = new FileTreeItem (token, fileIndex, totalSize);
- else
- child = new FileTreeItem (token);
- item->appendChild (child);
- endInsertRows ();
-
- rowsAdded.append (indexOf(child, 0));
- }
- item = child;
- }
-
- if (item != myRootItem)
- {
- assert (item->fileIndex() == fileIndex);
- assert (item->totalSize() == totalSize);
-
- myIndexCache[fileIndex] = item;
-
- const std::pair<int,int> changed = item->update (item->name(), wanted, priority, have, added || updateFields);
- if (changed.first >= 0)
- dataChanged (indexOf (item, changed.first), indexOf (item, changed.second));
- }
- }
-}
-
-void
-FileTreeModel::parentsChanged (const QModelIndex& index, int firstColumn, int lastColumn)
-{
- assert (firstColumn <= lastColumn);
-
- QModelIndex walk = index;
-
- for (;;)
- {
- walk = parent (walk, firstColumn);
- if (!walk.isValid ())
- break;
-
- dataChanged (walk, walk.sibling (walk.row (), lastColumn));
- }
-}
-
-void
-FileTreeModel::subtreeChanged (const QModelIndex& index, int firstColumn, int lastColumn)
-{
- assert (firstColumn <= lastColumn);
-
- const int childCount = rowCount (index);
- if (!childCount)
- return;
-
- // tell everyone that this tier changed
- dataChanged (index.child (0, firstColumn), index.child (childCount - 1, lastColumn));
-
- // walk the subtiers
- for (int i=0; i<childCount; ++i)
- subtreeChanged (index.child (i, 0), firstColumn, lastColumn);
-}
-
-void
-FileTreeModel::clicked (const QModelIndex& index)
-{
- const int column (index.column());
-
- if (!index.isValid())
- return;
-
- if (column == COL_WANTED)
- {
- bool want;
- QSet<int> file_ids;
- FileTreeItem * item;
-
- item = itemFromIndex (index);
- item->twiddleWanted (file_ids, want);
- emit wantedChanged (file_ids, want);
-
- dataChanged (index, index);
- parentsChanged (index, COL_SIZE, COL_WANTED);
- subtreeChanged (index, COL_WANTED, COL_WANTED);
- }
- else if (column == COL_PRIORITY)
- {
- int priority;
- QSet<int> file_ids;
- FileTreeItem * item;
-
- item = itemFromIndex (index);
- item->twiddlePriority (file_ids, priority);
- emit priorityChanged (file_ids, priority);
-
- dataChanged (index, index);
- parentsChanged (index, column, column);
- subtreeChanged (index, column, column);
- }
-}
-
-void
-FileTreeModel::doubleClicked (const QModelIndex& index)
-{
- if (!index.isValid())
- return;
-
- const int column (index.column());
- if (column == COL_WANTED || column == COL_PRIORITY)
- return;
-
- FileTreeItem * item = itemFromIndex (index);
-
- if (item->childCount () == 0 && item->isComplete ())
- emit openRequested (item->path ());
-}
-
-/****
-*****
-****/
-
-QSize
-FileTreeDelegate::sizeHint(const QStyleOptionViewItem& item, const QModelIndex& index) const
-{
- QSize size;
-
- switch(index.column())
- {
- case COL_PROGRESS:
- case COL_WANTED:
- size = QSize(20, 1);
- break;
-
- default:
- size = QItemDelegate::sizeHint (item, index);
- }
-
- size.rheight() += 8; // make the spacing a little nicer
- return size;
-}
-
-void
-FileTreeDelegate::paint (QPainter * painter,
- const QStyleOptionViewItem & option,
- const QModelIndex & index) const
-{
- const int column(index.column());
-
- if ((column != COL_PROGRESS) && (column != COL_WANTED))
- {
- QItemDelegate::paint(painter, option, index);
- return;
- }
-
- QStyle * style (qApp->style ());
-
- painter->save();
- QItemDelegate::drawBackground (painter, option, index);
-
- if(column == COL_PROGRESS)
- {
- QStyleOptionProgressBar p;
- p.state = option.state | QStyle::State_Small;
- p.direction = qApp->layoutDirection();
- p.rect = option.rect;
- p.rect.setSize (QSize(option.rect.width()-2, option.rect.height()-8));
- p.rect.moveCenter (option.rect.center());
- p.fontMetrics = qApp->fontMetrics();
- p.minimum = 0;
- p.maximum = 100;
- p.textAlignment = Qt::AlignCenter;
- p.textVisible = true;
- p.progress = (int)(100.0*index.data().toDouble());
- p.text = QString::fromLatin1 ("%1%").arg (p.progress);
- style->drawControl(QStyle::CE_ProgressBar, &p, painter);
- }
- else if(column == COL_WANTED)
- {
- QStyleOptionButton o;
- o.state = option.state;
- o.direction = qApp->layoutDirection();
- o.rect.setSize (QSize(20, option.rect.height()));
- o.rect.moveCenter (option.rect.center());
- o.fontMetrics = qApp->fontMetrics();
- switch (index.data().toInt())
- {
- case Qt::Unchecked: o.state |= QStyle::State_Off; break;
- case Qt::Checked: o.state |= QStyle::State_On; break;
- default: o.state |= QStyle::State_NoChange;break;
- }
- style->drawControl (QStyle::CE_CheckBox, &o, painter);
- }
-
- QItemDelegate::drawFocus (painter, option, option.rect);
- painter->restore();
-}
-
-/****
-*****
-*****
-*****
-****/
-
-FileTreeView::FileTreeView (QWidget * parent, bool isEditable):
- QTreeView (parent),
- myModel (this, isEditable),
- myProxy (new QSortFilterProxyModel()),
- myDelegate (this)
-{
- setSortingEnabled (true);
- setAlternatingRowColors (true);
- setSelectionBehavior (QAbstractItemView::SelectRows);
- setSelectionMode (QAbstractItemView::ExtendedSelection);
- myProxy->setSourceModel (&myModel);
- setModel (myProxy);
- setItemDelegate (&myDelegate);
- setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
- sortByColumn (COL_NAME, Qt::AscendingOrder);
- installEventFilter (this);
-
- for (int i=0; i<NUM_COLUMNS; ++i)
- {
- setColumnHidden (i, (i<FIRST_VISIBLE_COLUMN) || (LAST_VISIBLE_COLUMN<i));
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
- header()->setResizeMode(i, QHeaderView::Interactive);
-#else
- header()->setSectionResizeMode(i, QHeaderView::Interactive);
-#endif
- }
-
- connect (this, SIGNAL(clicked(QModelIndex)),
- this, SLOT(onClicked(QModelIndex)));
-
- connect (this, SIGNAL(doubleClicked(QModelIndex)),
- this, SLOT(onDoubleClicked(QModelIndex)));
-
- connect (&myModel, SIGNAL(priorityChanged(QSet<int>, int)),
- this, SIGNAL(priorityChanged(QSet<int>, int)));
-
- connect (&myModel, SIGNAL(wantedChanged(QSet<int>, bool)),
- this, SIGNAL(wantedChanged(QSet<int>, bool)));
-
- connect (&myModel, SIGNAL(pathEdited(QString, QString)),
- this, SIGNAL(pathEdited(QString, QString)));
-
- connect (&myModel, SIGNAL (openRequested (QString)),
- this, SLOT (onOpenRequested (QString)),
- Qt::QueuedConnection);
-}
-
-FileTreeView::~FileTreeView ()
-{
- myProxy->deleteLater();
-}
-
-void
-FileTreeView::onClicked (const QModelIndex& proxyIndex)
-{
- const QModelIndex modelIndex = myProxy->mapToSource (proxyIndex);
- myModel.clicked (modelIndex);
-}
-
-void
-FileTreeView::onDoubleClicked (const QModelIndex& proxyIndex)
-{
- const QModelIndex modelIndex = myProxy->mapToSource (proxyIndex);
- myModel.doubleClicked (modelIndex);
-}
-
-void
-FileTreeView::onOpenRequested (const QString& path)
-{
- if (state () == EditingState)
- return;
-
- emit openRequested (path);
-}
-
-bool
-FileTreeView::eventFilter (QObject * o, QEvent * event)
-{
- // this is kind of a hack to get the last three columns be the
- // right size, and to have the filename column use whatever
- // space is left over...
- if ((o == this) && (event->type() == QEvent::Resize))
- {
- QResizeEvent * r = static_cast<QResizeEvent*> (event);
- int left = r->size().width();
- const QFontMetrics fontMetrics(font());
- for (int column=FIRST_VISIBLE_COLUMN; column<=LAST_VISIBLE_COLUMN; ++column)
- {
- if (column == COL_NAME)
- continue;
- if (isColumnHidden (column))
- continue;
-
- QString header;
- if (column == COL_SIZE)
- header = QLatin1String ("999.9 KiB");
- else
- header = myModel.headerData (column, Qt::Horizontal).toString();
- header += QLatin1String (" ");
- const int width = fontMetrics.size (0, header).width();
- setColumnWidth (column, width);
- left -= width;
- }
- left -= 20; // not sure why this is necessary. it works in different themes + font sizes though...
- setColumnWidth(COL_NAME, std::max(left,0));
- }
-
- // handle using the keyboard to toggle the
- // wanted/unwanted state or the file priority
- else if (event->type () == QEvent::KeyPress && state () != EditingState)
- {
- switch (static_cast<QKeyEvent*> (event)->key ())
- {
- case Qt::Key_Space:
- for (const QModelIndex& i: selectionModel ()->selectedRows (COL_WANTED))
- clicked (i);
- break;
-
- case Qt::Key_Enter:
- case Qt::Key_Return:
- for (const QModelIndex& i: selectionModel ()->selectedRows (COL_PRIORITY))
- clicked (i);
- break;
- }
- }
-
- return false;
-}
-
-void
-FileTreeView::update (const FileList& files, bool updateFields)
-{
- for (const TrFile& file: files)
- {
- QList<QModelIndex> added;
- myModel.addFile (file.index, file.filename, file.wanted, file.priority, file.size, file.have, added, updateFields);
- for (const QModelIndex& i: added)
- expand (myProxy->mapFromSource(i));
- }
-}
-
-void
-FileTreeView::clear ()
-{
- myModel.clear();
-}
-
-void
-FileTreeView::setEditable (bool editable)
-{
- myModel.setEditable (editable);
-}
+++ /dev/null
-/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
- *
- * It may be used under the GNU GPL versions 2 or 3
- * or any future license endorsed by Mnemosyne LLC.
- *
- * $Id$
- */
-
-#ifndef QTR_FILE_TREE
-#define QTR_FILE_TREE
-
-#include <QAbstractItemModel>
-#include <QObject>
-#include <QItemDelegate>
-#include <QList>
-#include <QHash>
-#include <QMap>
-#include <QSet>
-#include <QSize>
-#include <QString>
-#include <QTreeView>
-#include <QVariant>
-
-class QSortFilterProxyModel;
-class QStyle;
-
-#include "torrent.h" // FileList
-
-/****
-*****
-****/
-
-class FileTreeItem: public QObject
-{
- Q_OBJECT
-
- enum { LOW=(1<<0), NORMAL=(1<<1), HIGH=(1<<2) };
-
- public:
-
- virtual ~FileTreeItem();
-
- FileTreeItem (const QString& name=QString (), int fileIndex=-1, uint64_t size=0):
- myFileIndex (fileIndex),
- myParent (0),
- myName (name),
- myPriority (0),
- myIsWanted (0),
- myHaveSize (0),
- myTotalSize (size),
- myFirstUnhashedRow (0) {}
-
- public:
- void appendChild (FileTreeItem *child);
- FileTreeItem * child (const QString& filename);
- FileTreeItem * child (int row) { return myChildren.at(row); }
- int childCount () const { return myChildren.size(); }
- FileTreeItem * parent () { return myParent; }
- const FileTreeItem * parent () const { return myParent; }
- int row () const;
- const QString& name () const { return myName; }
- QVariant data (int column, int role) const;
- std::pair<int,int> update (const QString& name, bool want, int priority, uint64_t have, bool updateFields);
- void twiddleWanted (QSet<int>& fileIds, bool&);
- void twiddlePriority (QSet<int>& fileIds, int&);
- int fileIndex () const { return myFileIndex; }
- uint64_t totalSize () const { return myTotalSize; }
- QString path () const;
- bool isComplete () const;
-
- private:
- void setSubtreePriority (int priority, QSet<int>& fileIds);
- void setSubtreeWanted (bool, QSet<int>& fileIds);
- QString priorityString () const;
- QString sizeString () const;
- void getSubtreeWantedSize (uint64_t& have, uint64_t& total) const;
- double progress () const;
- int priority () const;
- int isSubtreeWanted () const;
-
- const int myFileIndex;
- FileTreeItem * myParent;
- QList<FileTreeItem*> myChildren;
- QHash<QString,int> myChildRows;
- const QHash<QString,int>& getMyChildRows();
- QString myName;
- int myPriority;
- bool myIsWanted;
- uint64_t myHaveSize;
- const uint64_t myTotalSize;
- size_t myFirstUnhashedRow;
-};
-
-class FileTreeModel: public QAbstractItemModel
-{
- Q_OBJECT
-
- public:
- FileTreeModel (QObject *parent = 0, bool isEditable = true);
- ~FileTreeModel ();
-
- void setEditable (bool editable);
-
- public:
- QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const;
- Qt::ItemFlags flags (const QModelIndex& index) const;
- QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
- QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex()) const;
- QModelIndex parent (const QModelIndex& child) const;
- QModelIndex parent (const QModelIndex& child, int column) const;
- int rowCount (const QModelIndex& parent = QModelIndex()) const;
- int columnCount (const QModelIndex &parent = QModelIndex()) const;
- virtual bool setData (const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
-
- signals:
- void priorityChanged (const QSet<int>& fileIndices, int);
- void wantedChanged (const QSet<int>& fileIndices, bool);
- void pathEdited (const QString& oldpath, const QString& newname);
- void openRequested (const QString& path);
-
- public:
- void clear ();
- void addFile (int index, const QString& filename,
- bool wanted, int priority,
- uint64_t size, uint64_t have,
- QList<QModelIndex>& rowsAdded,
- bool torrentChanged);
-
- private:
- void clearSubtree (const QModelIndex &);
- QModelIndex indexOf (FileTreeItem *, int column) const;
- void parentsChanged (const QModelIndex &, int firstColumn, int lastColumn);
- void subtreeChanged (const QModelIndex &, int firstColumn, int lastColumn);
- FileTreeItem * findItemForFileIndex (int fileIndex) const;
- FileTreeItem * itemFromIndex (const QModelIndex&) const;
-
- private:
- FileTreeItem * myRootItem;
- QMap<int, FileTreeItem *> myIndexCache;
- bool myIsEditable;
-
- public slots:
- void clicked (const QModelIndex & index);
- void doubleClicked (const QModelIndex & index);
-};
-
-class FileTreeDelegate: public QItemDelegate
-{
- Q_OBJECT
-
- public:
- FileTreeDelegate (QObject * parent=0): QItemDelegate(parent) {}
- virtual ~FileTreeDelegate() {}
-
- public:
- virtual QSize sizeHint (const QStyleOptionViewItem&, const QModelIndex&) const;
- virtual void paint (QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const;
-};
-
-class FileTreeView: public QTreeView
-{
- Q_OBJECT
-
- public:
- FileTreeView (QWidget * parent=0, bool editable=true);
- virtual ~FileTreeView ();
- void clear ();
- void update (const FileList& files, bool updateProperties=true);
-
- void setEditable (bool editable);
-
- signals:
- void priorityChanged (const QSet<int>& fileIndices, int priority);
- void wantedChanged (const QSet<int>& fileIndices, bool wanted);
- void pathEdited (const QString& oldpath, const QString& newname);
- void openRequested (const QString& path);
-
- protected:
- bool eventFilter (QObject *, QEvent *);
-
- private:
- FileTreeModel myModel;
- QSortFilterProxyModel * myProxy;
- FileTreeDelegate myDelegate;
-
- public slots:
- void onClicked (const QModelIndex& index);
- void onDoubleClicked (const QModelIndex& index);
- void onOpenRequested (const QString& path);
-};
-
-#endif
+++ /dev/null
-/*
- * This file Copyright (C) 2012-2014 Mnemosyne LLC
- *
- * It may be used under the GNU GPL versions 2 or 3
- * or any future license endorsed by Mnemosyne LLC.
- *
- * $Id$
- */
-
-#include <QAbstractItemView>
-#include <QLabel>
-#include <QHBoxLayout>
-#include <QStylePainter>
-#include <QString>
-#include <QToolButton>
-#include <QtGui>
-
-#include "app.h"
-#include "favicon.h"
-#include "filters.h"
-#include "filterbar.h"
-#include "hig.h"
-#include "prefs.h"
-#include "torrent-filter.h"
-#include "torrent-model.h"
-#include "utils.h"
-
-/****
-*****
-***** DELEGATE
-*****
-****/
-
-enum
-{
- TorrentCountRole = Qt::UserRole + 1,
- TorrentCountStringRole,
- ActivityRole,
- TrackerRole
-};
-
-namespace
-{
- int getHSpacing (const QWidget * w)
- {
- return qMax (int (HIG::PAD_SMALL), w->style ()->pixelMetric (QStyle::PM_LayoutHorizontalSpacing, 0, w));
- }
-
- QColor
- getFadedColor (const QColor& color)
- {
- QColor fadedColor (color);
- fadedColor.setAlpha (128);
- return fadedColor;
- }
-}
-
-FilterBarComboBoxDelegate::FilterBarComboBoxDelegate (QObject * parent, QComboBox * combo):
- QItemDelegate (parent),
- myCombo (combo)
-{
-}
-
-bool
-FilterBarComboBoxDelegate::isSeparator (const QModelIndex& index)
-{
- return index.data (Qt::AccessibleDescriptionRole).toString () == QLatin1String ("separator");
-}
-void
-FilterBarComboBoxDelegate::setSeparator (QAbstractItemModel * model, const QModelIndex& index)
-{
- model->setData (index, QString::fromLatin1 ("separator"), Qt::AccessibleDescriptionRole);
-
- if (QStandardItemModel *m = qobject_cast<QStandardItemModel*> (model))
- if (QStandardItem *item = m->itemFromIndex (index))
- item->setFlags (item->flags () & ~ (Qt::ItemIsSelectable|Qt::ItemIsEnabled));
-}
-
-void
-FilterBarComboBoxDelegate::paint (QPainter * painter,
- const QStyleOptionViewItem & option,
- const QModelIndex & index) const
-{
- if (isSeparator (index))
- {
- QRect rect = option.rect;
- if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3*> (&option))
- if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView*> (v3->widget))
- rect.setWidth (view->viewport ()->width ());
- QStyleOption opt;
- opt.rect = rect;
- myCombo->style ()->drawPrimitive (QStyle::PE_IndicatorToolBarSeparator, &opt, painter, myCombo);
- }
- else
- {
- QStyleOptionViewItem disabledOption = option;
- const QPalette::ColorRole disabledColorRole = (disabledOption.state & QStyle::State_Selected) ?
- QPalette::HighlightedText : QPalette::Text;
- disabledOption.palette.setColor (disabledColorRole, getFadedColor (disabledOption.palette.color (disabledColorRole)));
-
- QRect boundingBox = option.rect;
-
- const int hmargin = getHSpacing (myCombo);
- boundingBox.adjust (hmargin, 0, -hmargin, 0);
-
- QRect decorationRect = rect (option, index, Qt::DecorationRole);
- decorationRect.setSize (myCombo->iconSize ());
- decorationRect = QStyle::alignedRect (option.direction,
- Qt::AlignLeft|Qt::AlignVCenter,
- decorationRect.size (), boundingBox);
- Utils::narrowRect (boundingBox, decorationRect.width () + hmargin, 0, option.direction);
-
- QRect countRect = rect (option, index, TorrentCountStringRole);
- countRect = QStyle::alignedRect (option.direction,
- Qt::AlignRight|Qt::AlignVCenter,
- countRect.size (), boundingBox);
- Utils::narrowRect (boundingBox, 0, countRect.width () + hmargin, option.direction);
- const QRect displayRect = boundingBox;
-
- drawBackground (painter, option, index);
- QStyleOptionViewItem option2 = option;
- option2.decorationSize = myCombo->iconSize ();
- drawDecoration (painter, option, decorationRect, decoration (option2,index.data (Qt::DecorationRole)));
- drawDisplay (painter, option, displayRect, index.data (Qt::DisplayRole).toString ());
- drawDisplay (painter, disabledOption, countRect, index.data (TorrentCountStringRole).toString ());
- drawFocus (painter, option, displayRect|countRect);
- }
-}
-
-QSize
-FilterBarComboBoxDelegate::sizeHint (const QStyleOptionViewItem & option,
- const QModelIndex & index) const
-{
- if (isSeparator (index))
- {
- const int pm = myCombo->style ()->pixelMetric (QStyle::PM_DefaultFrameWidth, 0, myCombo);
- return QSize (pm, pm + 10);
- }
- else
- {
- QStyle * s = myCombo->style ();
- const int hmargin = getHSpacing (myCombo);
-
- QSize size = QItemDelegate::sizeHint (option, index);
- size.setHeight (qMax (size.height (), myCombo->iconSize ().height () + 6));
- size.rwidth () += s->pixelMetric (QStyle::PM_FocusFrameHMargin, 0, myCombo);
- size.rwidth () += rect (option,index,TorrentCountStringRole).width ();
- size.rwidth () += hmargin * 4;
- return size;
- }
-}
-
-/**
-***
-**/
-
-FilterBarComboBox::FilterBarComboBox (QWidget * parent):
- QComboBox (parent)
-{
- setSizeAdjustPolicy (QComboBox::AdjustToContents);
-}
-
-int
-FilterBarComboBox::currentCount () const
-{
- int count = 0;
-
- const QModelIndex modelIndex = model ()->index (currentIndex (), 0, rootModelIndex ());
- if (modelIndex.isValid ())
- count = modelIndex.data (TorrentCountRole).toInt ();
-
- return count;
-}
-
-QSize
-FilterBarComboBox::minimumSizeHint () const
-{
- QFontMetrics fm (fontMetrics ());
- const QSize textSize = fm.boundingRect (itemText (0)).size ();
- const QSize countSize = fm.boundingRect (itemData (0, TorrentCountStringRole).toString ()).size ();
- return calculateSize (textSize, countSize);
-}
-
-QSize
-FilterBarComboBox::sizeHint () const
-{
- QFontMetrics fm (fontMetrics ());
- QSize maxTextSize (0, 0);
- QSize maxCountSize (0, 0);
- for (int i = 0, n = count (); i < n; ++i)
- {
- const QSize textSize = fm.boundingRect (itemText (i)).size ();
- maxTextSize.setHeight (qMax (maxTextSize.height (), textSize.height ()));
- maxTextSize.setWidth (qMax (maxTextSize.width (), textSize.width ()));
-
- const QSize countSize = fm.boundingRect (itemData (i, TorrentCountStringRole).toString ()).size ();
- maxCountSize.setHeight (qMax (maxCountSize.height (), countSize.height ()));
- maxCountSize.setWidth (qMax (maxCountSize.width (), countSize.width ()));
- }
-
- return calculateSize (maxTextSize, maxCountSize);
-}
-
-QSize
-FilterBarComboBox::calculateSize (const QSize& textSize, const QSize& countSize) const
-{
- const int hmargin = getHSpacing (this);
-
- QStyleOptionComboBox option;
- initStyleOption (&option);
-
- QSize contentSize = iconSize () + QSize (4, 2);
- contentSize.setHeight (qMax (contentSize.height (), textSize.height ()));
- contentSize.rwidth () += hmargin + textSize.width ();
- contentSize.rwidth () += hmargin + countSize.width ();
-
- return style ()->sizeFromContents (QStyle::CT_ComboBox, &option, contentSize, this).expandedTo (qApp->globalStrut ());
-}
-
-void
-FilterBarComboBox::paintEvent (QPaintEvent * e)
-{
- Q_UNUSED (e);
-
- QStylePainter painter (this);
- painter.setPen (palette ().color (QPalette::Text));
-
- // draw the combobox frame, focusrect and selected etc.
- QStyleOptionComboBox opt;
- initStyleOption (&opt);
- painter.drawComplexControl (QStyle::CC_ComboBox, opt);
-
- // draw the icon and text
- const QModelIndex modelIndex = model ()->index (currentIndex (), 0, rootModelIndex ());
- if (modelIndex.isValid ())
- {
- QStyle * s = style ();
- const int hmargin = getHSpacing (this);
-
- QRect rect = s->subControlRect (QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);
- rect.adjust (2, 1, -2, -1);
-
- // draw the icon
- QPixmap pixmap;
- QVariant variant = modelIndex.data (Qt::DecorationRole);
- switch (variant.type ())
- {
- case QVariant::Pixmap: pixmap = qvariant_cast<QPixmap> (variant); break;
- case QVariant::Icon: pixmap = qvariant_cast<QIcon> (variant).pixmap (iconSize ()); break;
- default: break;
- }
- if (!pixmap.isNull ())
- {
- const QRect iconRect = QStyle::alignedRect(opt.direction, Qt::AlignLeft | Qt::AlignVCenter,
- opt.iconSize, rect);
- painter.drawPixmap (iconRect.topLeft (), pixmap);
- Utils::narrowRect (rect, iconRect.width () + hmargin, 0, opt.direction);
- }
-
- // draw the count
- QString text = modelIndex.data (TorrentCountStringRole).toString ();
- if (!text.isEmpty ())
- {
- const QPen pen = painter.pen ();
- painter.setPen (getFadedColor (pen.color ()));
- const QRect textRect = QStyle::alignedRect(opt.direction, Qt::AlignRight | Qt::AlignVCenter,
- QSize (opt.fontMetrics.width (text), rect.height ()), rect);
- painter.drawText (textRect, Qt::AlignRight | Qt::AlignVCenter, text);
- Utils::narrowRect (rect, 0, textRect.width () + hmargin, opt.direction);
- painter.setPen (pen);
- }
-
- // draw the text
- text = modelIndex.data (Qt::DisplayRole).toString ();
- text = painter.fontMetrics ().elidedText (text, Qt::ElideRight, rect.width ());
- painter.drawText (rect, Qt::AlignLeft | Qt::AlignVCenter, text);
- }
-}
-
-/****
-*****
-****/
-
-FilterBarLineEdit::FilterBarLineEdit (QWidget * parent):
- QLineEdit (parent),
- myClearButton (nullptr)
-{
-#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
- const QIcon icon = QIcon::fromTheme (QLatin1String ("edit-clear"), style ()->standardIcon (QStyle::SP_DialogCloseButton));
- const int iconSize = style ()->pixelMetric (QStyle::PM_SmallIconSize);
-
- myClearButton = new QToolButton (this);
- myClearButton->setStyleSheet (QLatin1String ("QToolButton{border:0;padding:0;margin:0}"));
- myClearButton->setToolButtonStyle (Qt::ToolButtonIconOnly);
- myClearButton->setFocusPolicy (Qt::NoFocus);
- myClearButton->setCursor (Qt::ArrowCursor);
- myClearButton->setIconSize (QSize (iconSize, iconSize));
- myClearButton->setIcon (icon);
- myClearButton->setFixedSize (myClearButton->iconSize () + QSize (2, 2));
- myClearButton->hide ();
-
- const int frameWidth = style ()->pixelMetric (QStyle::PM_DefaultFrameWidth);
- const QSize minSizeHint = minimumSizeHint ();
- const QSize buttonSize = myClearButton->size ();
-
- setStyleSheet (QString::fromLatin1 ("QLineEdit{padding-right:%1px}").arg (buttonSize.width () + frameWidth + 1));
- setMinimumSize (qMax (minSizeHint.width (), buttonSize.width () + frameWidth * 2 + 2),
- qMax (minSizeHint.height (), buttonSize.height () + frameWidth * 2 + 2));
-
- connect (this, SIGNAL (textChanged (QString)), this, SLOT (updateClearButtonVisibility ()));
- connect (myClearButton, SIGNAL (clicked ()), this, SLOT (clear ()));
-#else
- setClearButtonEnabled (true);
-#endif
-
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
- setPlaceholderText (tr ("Search..."));
-#endif
-}
-
-void
-FilterBarLineEdit::resizeEvent (QResizeEvent * event)
-{
- QLineEdit::resizeEvent (event);
-
-#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
- const int frameWidth = style ()->pixelMetric (QStyle::PM_DefaultFrameWidth);
- const QRect editRect = rect();
- const QSize buttonSize = myClearButton->size ();
-
- myClearButton->move (editRect.right () - frameWidth - buttonSize.width (),
- editRect.top () + (editRect.height () - buttonSize.height ()) / 2);
-#endif
-}
-
-void
-FilterBarLineEdit::updateClearButtonVisibility ()
-{
-#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
- myClearButton->setVisible (!text ().isEmpty ());
-#endif
-}
-
-/****
-*****
-***** ACTIVITY
-*****
-****/
-
-FilterBarComboBox *
-FilterBar::createActivityCombo ()
-{
- FilterBarComboBox * c = new FilterBarComboBox (this);
- FilterBarComboBoxDelegate * delegate = new FilterBarComboBoxDelegate (this, c);
- c->setItemDelegate (delegate);
-
- QStandardItemModel * model = new QStandardItemModel (this);
-
- QStandardItem * row = new QStandardItem (tr ("All"));
- row->setData (FilterMode::SHOW_ALL, ActivityRole);
- model->appendRow (row);
-
- model->appendRow (new QStandardItem); // separator
- delegate->setSeparator (model, model->index (1, 0));
-
- row = new QStandardItem (QIcon::fromTheme (QLatin1String ("system-run")), tr ("Active"));
- row->setData (FilterMode::SHOW_ACTIVE, ActivityRole);
- model->appendRow (row);
-
- row = new QStandardItem (QIcon::fromTheme (QLatin1String ("go-down")), tr ("Downloading"));
- row->setData (FilterMode::SHOW_DOWNLOADING, ActivityRole);
- model->appendRow (row);
-
- row = new QStandardItem (QIcon::fromTheme (QLatin1String ("go-up")), tr ("Seeding"));
- row->setData (FilterMode::SHOW_SEEDING, ActivityRole);
- model->appendRow (row);
-
- row = new QStandardItem (QIcon::fromTheme (QLatin1String ("media-playback-pause")), tr ("Paused"));
- row->setData (FilterMode::SHOW_PAUSED, ActivityRole);
- model->appendRow (row);
-
- row = new QStandardItem (QIcon::fromTheme (QLatin1String ("dialog-ok")), tr ("Finished"));
- row->setData (FilterMode::SHOW_FINISHED, ActivityRole);
- model->appendRow (row);
-
- row = new QStandardItem (QIcon::fromTheme (QLatin1String ("view-refresh")), tr ("Verifying"));
- row->setData (FilterMode::SHOW_VERIFYING, ActivityRole);
- model->appendRow (row);
-
- row = new QStandardItem (QIcon::fromTheme (QLatin1String ("process-stop")), tr ("Error"));
- row->setData (FilterMode::SHOW_ERROR, ActivityRole);
- model->appendRow (row);
-
- c->setModel (model);
- return c;
-}
-
-/****
-*****
-*****
-*****
-****/
-
-namespace
-{
- QString readableHostName (const QString& host)
- {
- // get the readable name...
- QString name = host;
- const int pos = name.lastIndexOf (QLatin1Char ('.'));
- if (pos >= 0)
- name.truncate (pos);
- if (!name.isEmpty ())
- name[0] = name[0].toUpper ();
- return name;
- }
-}
-
-void
-FilterBar::refreshTrackers ()
-{
- Favicons& favicons = qApp->favicons;
- const int firstTrackerRow = 2; // skip over the "All" and separator...
-
- // pull info from the tracker model...
- QSet<QString> oldHosts;
- for (int row=firstTrackerRow; ; ++row)
- {
- QModelIndex index = myTrackerModel->index (row, 0);
- if (!index.isValid ())
- break;
- oldHosts << index.data (TrackerRole).toString ();
- }
-
- // pull the new stats from the torrent model...
- QSet<QString> newHosts;
- QMap<QString,int> torrentsPerHost;
- for (int row=0; ; ++row)
- {
- QModelIndex index = myTorrents.index (row, 0);
- if (!index.isValid ())
- break;
- const Torrent * tor = index.data (TorrentModel::TorrentRole).value<const Torrent*> ();
- QSet<QString> torrentNames;
- for (const QString& host: tor->hosts ())
- {
- newHosts.insert (host);
- torrentNames.insert (readableHostName (host));
- }
- for (const QString& name: torrentNames)
- ++torrentsPerHost[name];
- }
-
- // update the "All" row
- myTrackerModel->setData (myTrackerModel->index (0,0), myTorrents.rowCount (), TorrentCountRole);
- myTrackerModel->setData (myTrackerModel->index (0,0), getCountString (myTorrents.rowCount ()), TorrentCountStringRole);
-
- // rows to update
- for (const QString& host: oldHosts & newHosts)
- {
- const QString name = readableHostName (host);
- QStandardItem * row = myTrackerModel->findItems (name).front ();
- const int count = torrentsPerHost[name];
- row->setData (count, TorrentCountRole);
- row->setData (getCountString (count), TorrentCountStringRole);
- row->setData (favicons.findFromHost (host), Qt::DecorationRole);
- }
-
- // rows to remove
- for (const QString& host: oldHosts - newHosts)
- {
- const QString name = readableHostName (host);
- QStandardItem * item = myTrackerModel->findItems (name).front ();
- if (!item->data (TrackerRole).toString ().isEmpty ()) // don't remove "All"
- myTrackerModel->removeRows (item->row (), 1);
- }
-
- // rows to add
- bool anyAdded = false;
- for (const QString& host: newHosts - oldHosts)
- {
- const QString name = readableHostName (host);
-
- if (!myTrackerModel->findItems (name).isEmpty ())
- continue;
-
- // find the sorted position to add this row
- int i = firstTrackerRow;
- for (int n=myTrackerModel->rowCount (); i<n; ++i)
- {
- const QString rowName = myTrackerModel->index (i,0).data (Qt::DisplayRole).toString ();
- if (rowName >= name)
- break;
- }
-
- // add the row
- QStandardItem * row = new QStandardItem (favicons.findFromHost (host), name);
- const int count = torrentsPerHost[host];
- row->setData (count, TorrentCountRole);
- row->setData (getCountString (count), TorrentCountStringRole);
- row->setData (favicons.findFromHost (host), Qt::DecorationRole);
- row->setData (host, TrackerRole);
- myTrackerModel->insertRow (i, row);
- anyAdded = true;
- }
-
- if (anyAdded) // the one added might match our filter...
- refreshPref (Prefs::FILTER_TRACKERS);
-}
-
-
-FilterBarComboBox *
-FilterBar::createTrackerCombo (QStandardItemModel * model)
-{
- FilterBarComboBox * c = new FilterBarComboBox (this);
- FilterBarComboBoxDelegate * delegate = new FilterBarComboBoxDelegate (this, c);
- c->setItemDelegate (delegate);
-
- QStandardItem * row = new QStandardItem (tr ("All"));
- row->setData (QString (), TrackerRole);
- const int count = myTorrents.rowCount ();
- row->setData (count, TorrentCountRole);
- row->setData (getCountString (count), TorrentCountStringRole);
- model->appendRow (row);
-
- model->appendRow (new QStandardItem); // separator
- delegate->setSeparator (model, model->index (1, 0));
-
- c->setModel (model);
- return c;
-}
-
-/****
-*****
-*****
-*****
-****/
-
-FilterBar::FilterBar (Prefs& prefs, const TorrentModel& torrents, const TorrentFilter& filter, QWidget * parent):
- QWidget (parent),
- myPrefs (prefs),
- myTorrents (torrents),
- myFilter (filter),
- myRecountTimer (new QTimer (this)),
- myIsBootstrapping (true)
-{
- QHBoxLayout * h = new QHBoxLayout (this);
- h->setContentsMargins (3, 3, 3, 3);
-
- myCountLabel = new QLabel (this);
- h->addWidget (myCountLabel);
-
- myActivityCombo = createActivityCombo ();
- myActivityCombo->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
- h->addWidget (myActivityCombo);
-
- myTrackerModel = new QStandardItemModel (this);
- myTrackerCombo = createTrackerCombo (myTrackerModel);
- h->addWidget (myTrackerCombo);
-
- myLineEdit = new FilterBarLineEdit (this);
- h->addWidget (myLineEdit);
- connect (myLineEdit, SIGNAL (textChanged (QString)), this, SLOT (onTextChanged (QString)));
-
- // listen for changes from the other players
- connect (&myPrefs, SIGNAL (changed (int)), this, SLOT (refreshPref (int)));
- connect (myActivityCombo, SIGNAL (currentIndexChanged (int)), this, SLOT (onActivityIndexChanged (int)));
- connect (myTrackerCombo, SIGNAL (currentIndexChanged (int)), this, SLOT (onTrackerIndexChanged (int)));
- connect (&myFilter, SIGNAL (rowsInserted (QModelIndex, int, int)), this, SLOT (refreshCountLabel ()));
- connect (&myFilter, SIGNAL (rowsRemoved (QModelIndex, int, int)), this, SLOT (refreshCountLabel ()));
- connect (&myTorrents, SIGNAL (modelReset ()), this, SLOT (onTorrentModelReset ()));
- connect (&myTorrents, SIGNAL (rowsInserted (QModelIndex, int, int)), this, SLOT (onTorrentModelRowsInserted (QModelIndex, int, int)));
- connect (&myTorrents, SIGNAL (rowsRemoved (QModelIndex, int, int)), this, SLOT (onTorrentModelRowsRemoved (QModelIndex, int, int)));
- connect (&myTorrents, SIGNAL (dataChanged (QModelIndex, QModelIndex)), this, SLOT (onTorrentModelDataChanged (QModelIndex, QModelIndex)));
- connect (myRecountTimer, SIGNAL (timeout ()), this, SLOT (recount ()));
-
- recountSoon ();
- refreshTrackers ();
- refreshCountLabel ();
- myIsBootstrapping = false;
-
- // initialize our state
- QList<int> initKeys;
- initKeys << Prefs::FILTER_MODE
- << Prefs::FILTER_TRACKERS;
- for (const int key: initKeys)
- refreshPref (key);
-}
-
-FilterBar::~FilterBar ()
-{
- delete myRecountTimer;
-}
-
-/***
-****
-***/
-
-void
-FilterBar::refreshPref (int key)
-{
- switch (key)
- {
- case Prefs::FILTER_MODE:
- {
- const FilterMode m = myPrefs.get<FilterMode> (key);
- QAbstractItemModel * model = myActivityCombo->model ();
- QModelIndexList indices = model->match (model->index (0,0), ActivityRole, m.mode ());
- myActivityCombo->setCurrentIndex (indices.isEmpty () ? 0 : indices.first ().row ());
- break;
- }
-
- case Prefs::FILTER_TRACKERS:
- {
- const QString tracker = myPrefs.getString (key);
- const QString name = readableHostName (tracker);
- QList<QStandardItem*> rows = myTrackerModel->findItems (name);
- if (!rows.isEmpty ())
- {
- myTrackerCombo->setCurrentIndex (rows.front ()->row ());
- }
- else // hm, we don't seem to have this tracker anymore...
- {
- const bool isBootstrapping = myTrackerModel->rowCount () <= 2;
- if (!isBootstrapping)
- myPrefs.set (key, QString ());
- }
- break;
- }
- }
-}
-
-void
-FilterBar::onTextChanged (const QString& str)
-{
- if (!myIsBootstrapping)
- myPrefs.set (Prefs::FILTER_TEXT, str.trimmed ());
-}
-
-void
-FilterBar::onTrackerIndexChanged (int i)
-{
- if (!myIsBootstrapping)
- {
- QString str;
- const bool isTracker = !myTrackerCombo->itemData (i,TrackerRole).toString ().isEmpty ();
- if (!isTracker)
- {
- // show all
- }
- else
- {
- str = myTrackerCombo->itemData (i,TrackerRole).toString ();
- const int pos = str.lastIndexOf (QLatin1Char ('.'));
- if (pos >= 0)
- str.truncate (pos+1);
- }
- myPrefs.set (Prefs::FILTER_TRACKERS, str);
- }
-}
-
-void
-FilterBar::onActivityIndexChanged (int i)
-{
- if (!myIsBootstrapping)
- {
- const FilterMode mode = myActivityCombo->itemData (i, ActivityRole).toInt ();
- myPrefs.set (Prefs::FILTER_MODE, mode);
- }
-}
-
-/***
-****
-***/
-
-void FilterBar::onTorrentModelReset () { recountSoon (); }
-void FilterBar::onTorrentModelRowsInserted (const QModelIndex&, int, int) { recountSoon (); }
-void FilterBar::onTorrentModelRowsRemoved (const QModelIndex&, int, int) { recountSoon (); }
-void FilterBar::onTorrentModelDataChanged (const QModelIndex&, const QModelIndex&) { recountSoon (); }
-
-void
-FilterBar::recountSoon ()
-{
- if (!myRecountTimer->isActive ())
- {
- myRecountTimer->setSingleShot (true);
- myRecountTimer->start (800);
- }
-}
-void
-FilterBar::recount ()
-{
- QAbstractItemModel * model = myActivityCombo->model ();
-
- int torrentsPerMode[FilterMode::NUM_MODES] = {};
- myFilter.countTorrentsPerMode (torrentsPerMode);
-
- for (int row=0, n=model->rowCount (); row<n; ++row)
- {
- QModelIndex index = model->index (row, 0);
- const int mode = index.data (ActivityRole).toInt ();
- const int count = torrentsPerMode [mode];
- model->setData (index, count, TorrentCountRole);
- model->setData (index, getCountString (count), TorrentCountStringRole);
- }
-
- refreshTrackers ();
- refreshCountLabel ();
-}
-
-QString
-FilterBar::getCountString (int n) const
-{
- return QString::fromLatin1 ("%L1").arg (n);
-}
-
-void
-FilterBar::refreshCountLabel ()
-{
- const int visibleCount = myFilter.rowCount ();
- const int trackerCount = myTrackerCombo->currentCount ();
- const int activityCount = myActivityCombo->currentCount ();
-
- if ((visibleCount == activityCount) || (visibleCount == trackerCount))
- myCountLabel->setText (tr("Show:"));
- else
- myCountLabel->setText (tr("Show %Ln of:", 0, visibleCount));
-}
+++ /dev/null
-/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
- *
- * It may be used under the GNU GPL versions 2 or 3
- * or any future license endorsed by Mnemosyne LLC.
- *
- * $Id$
- */
-
-#include <iostream>
-
-#include <QCheckBox>
-#include <QGridLayout>
-#include <QHBoxLayout>
-#include <QLabel>
-
-#include "hig.h"
-
-
-HIG::HIG (QWidget * parent):
- QWidget (parent),
- myRow (0),
- myHasTall (false),
- myGrid (new QGridLayout (this))
-{
- myGrid->setContentsMargins (PAD_BIG, PAD_BIG, PAD_BIG, PAD_BIG);
- myGrid->setHorizontalSpacing (PAD_BIG);
- myGrid->setVerticalSpacing (PAD);
- myGrid->setColumnStretch (1, 1);
-}
-
-HIG::~HIG ()
-{
- delete myGrid;
-}
-
-/***
-****
-***/
-
-void
-HIG::addSectionDivider ()
-{
- QWidget * w = new QWidget (this);
- myGrid->addWidget (w, myRow, 0, 1, 2);
- ++myRow;
-}
-
-void
-HIG::addSectionTitle (const QString& title)
-{
- QLabel * label = new QLabel (this);
- label->setText (title);
- label->setStyleSheet (QLatin1String ("font: bold"));
- label->setAlignment (Qt::AlignLeft|Qt::AlignVCenter);
- addSectionTitle (label);
-}
-
-void
-HIG::addSectionTitle (QWidget * w)
-{
- myGrid->addWidget (w, myRow, 0, 1, 2, Qt::AlignLeft|Qt::AlignVCenter);
- ++myRow;
-}
-
-void
-HIG::addSectionTitle (QLayout * l)
-{
- myGrid->addLayout (l, myRow, 0, 1, 2, Qt::AlignLeft|Qt::AlignVCenter);
- ++myRow;
-}
-
-
-QLayout *
-HIG::addRow (QWidget * w)
-{
- QHBoxLayout * h = new QHBoxLayout ();
- h->addSpacing (18);
- h->addWidget (w);
-
- QLabel * l;
- if ((l = qobject_cast<QLabel*>(w)))
- l->setAlignment (Qt::AlignLeft);
-
- return h;
-}
-
-void
-HIG::addWideControl (QLayout * l)
-{
- QHBoxLayout * h = new QHBoxLayout ();
- h->addSpacing (18);
- h->addLayout (l);
- myGrid->addLayout (h, myRow, 0, 1, 2, Qt::AlignLeft|Qt::AlignVCenter);
- ++myRow;
-}
-
-void
-HIG::addWideControl (QWidget * w)
-{
- QHBoxLayout * h = new QHBoxLayout ();
- h->addSpacing (18);
- h->addWidget (w);
- myGrid->addLayout (h, myRow, 0, 1, 2, Qt::AlignLeft|Qt::AlignVCenter);
- ++myRow;
-}
-
-QCheckBox*
-HIG::addWideCheckBox (const QString& text, bool isChecked)
-{
- QCheckBox * check = new QCheckBox (text, this);
- check->setChecked (isChecked);
- addWideControl (check);
- return check;
-}
-
-void
-HIG::addLabel (QWidget * w)
-{
- QHBoxLayout * h = new QHBoxLayout ();
- h->addSpacing (18);
- h->addWidget (w);
- myGrid->addLayout (h, myRow, 0, 1, 1, Qt::AlignLeft|Qt::AlignVCenter);
-}
-
-QLabel*
-HIG::addLabel (const QString& text)
-{
- QLabel * label = new QLabel (text, this);
- addLabel (label);
- return label;
-}
-
-void
-HIG::addTallLabel (QWidget * w)
-{
- QHBoxLayout * h = new QHBoxLayout ();
- h->addSpacing (18);
- h->addWidget (w);
- myGrid->addLayout (h, myRow, 0, 1, 1, Qt::AlignLeft|Qt::AlignTop);
-}
-
-QLabel*
-HIG::addTallLabel (const QString& text)
-{
- QLabel * label = new QLabel (text, this);
- addTallLabel (label);
- return label;
-}
-
-void
-HIG::addControl (QWidget * w)
-{
- myGrid->addWidget (w, myRow, 1, 1, 1);
-}
-
-void
-HIG::addControl (QLayout * l)
-{
- myGrid->addLayout (l, myRow, 1, 1, 1);
-}
-
-QLabel *
-HIG::addRow (const QString& text, QWidget * control, QWidget * buddy)
-{
- QLabel * label = addLabel (text);
- addControl (control);
- label->setBuddy (buddy ? buddy : control);
- ++myRow;
- return label;
-}
-
-QLabel *
-HIG::addTallRow (const QString& text, QWidget * control, QWidget * buddy)
-{
- QLabel* label = addTallLabel (text);
- label->setBuddy (buddy ? buddy : control);
- addControl (control);
- myHasTall = true;
- myGrid->setRowStretch (myRow, 1);
- ++myRow;
- return label;
-}
-
-QLabel *
-HIG::addRow (const QString& text, QLayout * control, QWidget * buddy)
-{
- QLabel * label = addLabel (text);
- addControl (control);
- if (buddy != 0)
- label->setBuddy (buddy);
- ++myRow;
- return label;
-}
-
-void
-HIG::addRow (QWidget * label, QWidget * control, QWidget * buddy)
-{
- addLabel (label);
-
- if (control)
- {
- addControl (control);
-
- QLabel * l = qobject_cast<QLabel*> (label);
- if (l != 0)
- l->setBuddy (buddy ? buddy : control);
- }
-
- ++myRow;
-}
-
-void
-HIG::addRow (QWidget * label, QLayout * control, QWidget * buddy)
-{
- addLabel (label);
-
- if (control)
- {
- addControl (control);
-
- QLabel * l = qobject_cast<QLabel*> (label);
- if (l != 0 && buddy != 0)
- l->setBuddy (buddy);
- }
-
- ++myRow;
-}
-
-void
-HIG::finish ()
-{
- if (!myHasTall)
- {
- QWidget * w = new QWidget (this);
- myGrid->addWidget (w, myRow, 0, 1, 2);
- myGrid->setRowStretch (myRow, 100);
- ++myRow;
- }
-}
+++ /dev/null
-/*
- * This file Copyright (C) 2009-2014 Mnemosyne LLC
- *
- * It may be used under the GNU GPL versions 2 or 3
- * or any future license endorsed by Mnemosyne LLC.
- *
- * $Id$
- */
-
-
-#ifndef QTR_HIG_H
-#define QTR_HIG_H
-
-#include <QWidget>
-
-class QCheckBox;
-class QLabel;
-class QString;
-class QGridLayout;
-class QLayout;
-
-class HIG: public QWidget
-{
- Q_OBJECT
-
- public:
-
- enum
- {
- PAD_SMALL = 3,
- PAD = 6,
- PAD_BIG = 12,
- PAD_LARGE = PAD_BIG
- };
-
- public:
-
- HIG (QWidget * parent = 0);
- virtual ~HIG ();
-
- public:
-
- void addSectionDivider ();
- void addSectionTitle (const QString&);
- void addSectionTitle (QWidget*);
- void addSectionTitle (QLayout*);
- void addWideControl (QLayout *);
- void addWideControl (QWidget *);
- QCheckBox* addWideCheckBox (const QString&, bool isChecked);
- QLabel* addLabel (const QString&);
- QLabel* addTallLabel (const QString&);
- void addLabel (QWidget *);
- void addTallLabel (QWidget *);
- void addControl (QWidget *);
- void addControl (QLayout *);
- QLabel* addRow (const QString & label, QWidget * control, QWidget * buddy=0);
- QLabel* addRow (const QString & label, QLayout * control, QWidget * buddy);
- void addRow (QWidget * label, QWidget * control, QWidget * buddy=0);
- void addRow (QWidget * label, QLayout * control, QWidget * buddy);
- QLabel* addTallRow (const QString & label, QWidget * control, QWidget * buddy=0);
- void finish ();
-
- private:
- QLayout* addRow (QWidget* w);
-
- private:
- int myRow;
- bool myHasTall;
- QGridLayout * myGrid;
-};
-
-#endif // QTR_HIG_H
translations/transmission_uk.ts \
translations/transmission_zh_CN.ts
-FORMS += about.ui \
- details.ui \
- mainwin.ui \
- make-dialog.ui \
- make-progress-dialog.ui \
- options.ui \
- prefs-dialog.ui \
- relocate.ui \
- session-dialog.ui \
- stats-dialog.ui
+FORMS += AboutDialog.ui \
+ DetailsDialog.ui \
+ MainWindow.ui \
+ MakeDialog.ui \
+ MakeProgressDialog.ui \
+ OptionsDialog.ui \
+ PrefsDialog.ui \
+ RelocateDialog.ui \
+ SessionDialog.ui \
+ StatsDialog.ui
RESOURCES += application.qrc
win32|macx:RESOURCES += icons/Faenza/Faenza.qrc
-SOURCES += about.cc \
- add-data.cc \
- app.cc \
- column-resizer.cc \
- dbus-adaptor.cc \
- details.cc \
- favicon.cc \
- file-tree.cc \
- filterbar.cc \
- filters.cc \
- freespace-label.cc \
- formatter.cc \
- hig.cc \
- license.cc \
- mainwin.cc \
- make-dialog.cc \
- options.cc \
- path-button.cc \
- prefs.cc \
- prefs-dialog.cc \
- relocate.cc \
- rpc-client.cc \
- session.cc \
- session-dialog.cc \
- squeezelabel.cc \
- stats-dialog.cc \
- torrent.cc torrent-delegate.cc \
- torrent-delegate-min.cc \
- torrent-filter.cc \
- torrent-model.cc \
- tracker-delegate.cc \
- tracker-model.cc \
- tracker-model-filter.cc \
- tricontoolbutton.cc \
- utils.cc \
- watchdir.cc
+SOURCES += AboutDialog.cc \
+ AddData.cc \
+ Application.cc \
+ ColumnResizer.cc \
+ DBusAdaptor.cc \
+ DetailsDialog.cc \
+ FaviconCache.cc \
+ FileTreeDelegate.cc \
+ FileTreeItem.cc \
+ FileTreeModel.cc \
+ FileTreeView.cc \
+ FilterBar.cc \
+ FilterBarComboBox.cc \
+ FilterBarComboBoxDelegate.cc \
+ FilterBarLineEdit.cc \
+ Filters.cc \
+ Formatter.cc \
+ FreeSpaceLabel.cc \
+ IconToolButton.cc \
+ LicenseDialog.cc \
+ MainWindow.cc \
+ MakeDialog.cc \
+ OptionsDialog.cc \
+ PathButton.cc \
+ Prefs.cc \
+ PrefsDialog.cc \
+ RelocateDialog.cc \
+ RpcClient.cc \
+ Session.cc \
+ SessionDialog.cc \
+ SqueezeLabel.cc \
+ StatsDialog.cc \
+ Torrent.cc \
+ TorrentDelegate.cc \
+ TorrentDelegateMin.cc \
+ TorrentFilter.cc \
+ TorrentModel.cc \
+ TrackerDelegate.cc \
+ TrackerModel.cc \
+ TrackerModelFilter.cc \
+ Utils.cc \
+ WatchDir.cc
HEADERS += $$replace(SOURCES, .cc, .h)
-HEADERS += speed.h types.h
+HEADERS += CustomVariantType.h Speed.h
win32:RC_FILE = qtr.rc