Changeset 124 in tspsg-svn for trunk/src


Ignore:
Timestamp:
Jul 4, 2010, 3:03:13 AM (14 years ago)
Author:
laleppa
Message:

+ Added support for Windows 7 Taskbar Extensions (namely, Progress Bars).

  • Cleanup is done in a separate thread now, so progress bar runs more smooth.
  • "Tabified" About dialog. Added GPL License and Credits.
  • Updated translations and tspsg.tag file.
Location:
trunk/src
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/mainwindow.cpp

    r123 r124  
    2323
    2424#include "mainwindow.h"
     25
     26#ifdef Q_OS_WIN32
     27        #include "shobjidl.h"
     28#endif
    2529
    2630#ifdef _T_T_L_
     
    436440void MainWindow::actionHelpAboutTriggered()
    437441{
     442        QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
     443
    438444QString title;
    439445#ifdef HANDHELD
     
    462468        about += QString("%1: <b>%2</b><br>").arg(tr("Algorithm"), CTSPSolver::getVersionId());
    463469        about += "<br>";
    464         about += tr("TSPSG is free software: you can redistribute it and/or modify it<br>"
    465                 "under the terms of the GNU General Public License as published<br>"
    466                 "by the Free Software Foundation, either version 3 of the License,<br>"
    467                 "or (at your option) any later version.<br>"
    468                 "<br>"
    469                 "TSPSG is distributed in the hope that it will be useful, but<br>"
    470                 "WITHOUT ANY WARRANTY; without even the implied warranty of<br>"
    471                 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>"
    472                 "GNU General Public License for more details.<br>"
    473                 "<br>"
    474                 "You should have received a copy of the GNU General Public License<br>"
    475                 "along with TSPSG.  If not, see <a href=\"http://www.gnu.org/licenses/\">http://www.gnu.org/licenses/</a>.");
     470        about += tr("This program is free software: you can redistribute it and/or modify<br>\n"
     471                "it under the terms of the GNU General Public License as published by<br>\n"
     472                "the Free Software Foundation, either version 3 of the License, or<br>\n"
     473                "(at your option) any later version.<br>\n"
     474                "<br>\n"
     475                "This program is distributed in the hope that it will be useful,<br>\n"
     476                "but WITHOUT ANY WARRANTY; without even the implied warranty of<br>\n"
     477                "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>\n"
     478                "GNU General Public License for more details.<br>\n"
     479                "<br>\n"
     480                "You should have received a copy of the GNU General Public License<br>\n"
     481                "along with TSPSG.  If not, see <a href=\"http://www.gnu.org/licenses/\">www.gnu.org/licenses/</a>.");
     482
     483QString credits;
     484        credits += tr("This software was created using LGPL version of <b>Qt framework</b>,<br>\n"
     485                "see <a href=\"http://qt.nokia.com/\">qt.nokia.com</a><br>\n"
     486                "<br>\n"
     487                "Most icons used in this software are part of <b>Oxygen Icons</b> project "
     488                "licensed according to the GNU Lesser General Public License,<br>\n"
     489                "see <a href=\"http://www.oxygen-icons.org/\">www.oxygen-icons.org</a><br>\n"
     490                "<br>\n"
     491                "Country flag icons used in this software are part of the free "
     492                "<b>Flag Icons</b> collection created by <b>IconDrawer</b>,<br>\n"
     493                "see <a href=\"http://www.icondrawer.com/\">www.icondrawer.com</a>");
     494
     495QFile f(":/files/COPYING");
     496        f.open(QIODevice::ReadOnly);
     497
     498QString translation = QApplication::translate("--------", "AUTHORS %1", "Please, provide translator credits here. %1 will be replaced with VERSION");
     499        if ((translation != "AUTHORS %1") && (translation.contains("%1"))) {
     500QString about = QApplication::translate("--------", "VERSION", "Please, provide your translation version here.");
     501                if (about != "VERSION")
     502                        translation = translation.arg(about);
     503        }
    476504
    477505QDialog *dlg = new QDialog(this);
    478506QLabel *lblIcon = new QLabel(dlg),
    479         *lblTitle = new QLabel(dlg),
    480         *lblTranslated = new QLabel(dlg);
     507        *lblTitle = new QLabel(dlg);
    481508#ifdef HANDHELD
    482509QLabel *lblSubTitle = new QLabel(QString("<b>&copy; 2007-%1 <a href=\"http://%2/\">%3</a></b>").arg(QDate::currentDate().toString("yyyy"), QApplication::organizationDomain(), QApplication::organizationName()), dlg);
    483510#endif // HANDHELD
     511QTabWidget *tabs = new QTabWidget(dlg);
    484512QTextBrowser *txtAbout = new QTextBrowser(dlg);
     513QTextBrowser *txtLicense = new QTextBrowser(dlg);
     514QTextBrowser *txtCredits = new QTextBrowser(dlg);
    485515QVBoxLayout *vb = new QVBoxLayout();
    486516QHBoxLayout *hb1 = new QHBoxLayout(),
     
    509539        txtAbout->setHtml(about);
    510540        txtAbout->moveCursor(QTextCursor::Start);
    511 #ifndef HANDHELD
    512         txtAbout->setStyleSheet(QString("QTextBrowser {background-color: %1; border-color: %2; border-width: 1px; border-style: solid; border-radius: 4px; padding: 1px;}").arg(palette().base().color().name(), palette().shadow().color().name()));
    513 #endif // HANDHELD
     541        txtAbout->setFrameShape(QFrame::NoFrame);
     542
     543//      txtCredits->setWordWrapMode(QTextOption::NoWrap);
     544        txtCredits->setOpenExternalLinks(true);
     545        txtCredits->setHtml(credits);
     546        txtCredits->moveCursor(QTextCursor::Start);
     547        txtCredits->setFrameShape(QFrame::NoFrame);
     548
     549        txtLicense->setWordWrapMode(QTextOption::NoWrap);
     550        txtLicense->setOpenExternalLinks(true);
     551        txtLicense->setText(f.readAll());
     552        txtLicense->moveCursor(QTextCursor::Start);
     553        txtLicense->setFrameShape(QFrame::NoFrame);
    514554
    515555        bb->button(QDialogButtonBox::Ok)->setCursor(QCursor(Qt::PointingHandCursor));
    516 
    517         lblTranslated->setText(QApplication::translate("--------", "AUTHORS", "Please, provide translator credits here."));
    518         if (lblTranslated->text() == "AUTHORS")
    519                 lblTranslated->hide();
    520         else {
    521                 lblTranslated->setOpenExternalLinks(true);
    522 #ifndef HANDHELD
    523                 lblTranslated->setStyleSheet(QString("QLabel {background-color: %1; border-color: %2; border-width: 1px; border-style: solid; border-radius: 3px; padding: 1px;}").arg(palette().alternateBase().color().name(), palette().shadow().color().name()));
    524 #endif // HANDHELD
    525                 hb2->addWidget(lblTranslated);
    526         }
    527 
    528         // This one isn't displayed anywhere, yet. Provided as a placeholder for future use.
    529         QApplication::translate("--------", "VERSION", "Please, provide your translation version here.");
    530556
    531557        hb2->addWidget(bb);
     
    538564        vb->addWidget(lblSubTitle);
    539565#endif // HANDHELD
    540         vb->addWidget(txtAbout);
     566
     567        tabs->addTab(txtAbout, tr("About"));
     568        tabs->addTab(txtLicense, tr("License"));
     569        tabs->addTab(txtCredits, tr("Credits"));
     570        if (translation != "AUTHORS %1") {
     571QTextBrowser *txtTranslation = new QTextBrowser(dlg);
     572//              txtTranslation->setWordWrapMode(QTextOption::NoWrap);
     573                txtTranslation->setOpenExternalLinks(true);
     574                txtTranslation->setText(translation);
     575                txtTranslation->moveCursor(QTextCursor::Start);
     576                txtTranslation->setFrameShape(QFrame::NoFrame);
     577
     578                tabs->addTab(txtTranslation, tr("Translation"));
     579        }
     580#ifndef HANDHELD
     581        tabs->setStyleSheet(QString("QTabWidget::pane {background-color: %1; border-color: %3; border-width: 1px; border-style: solid; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; padding: 1px;} QTabBar::tab {background-color: %2; border-color: %3; border-width: 1px; border-style: solid; border-bottom: none; border-top-left-radius: 4px; border-top-right-radius: 4px; padding: 2px 6px;} QTabBar::tab:selected {background-color: %4;} QTabBar::tab:!selected {margin-top: 1px;}").arg(palette().base().color().name(), palette().button().color().name(), palette().shadow().color().name(), palette().light().color().name()));
     582#endif // HANDHELD
     583
     584        vb->addWidget(tabs);
    541585        vb->addLayout(hb2);
    542586
     
    556600
    557601        dlg->resize(450, 350);
     602        QApplication::restoreOverrideCursor();
    558603
    559604        dlg->exec();
     
    597642        pb->setFormat(tr("%v of %1 parts found").arg(n));
    598643        pd.setBar(pb);
     644QPushButton *cancel = new QPushButton(&pd);
     645        cancel->setIcon(QIcon::fromTheme("dialog-cancel", QIcon(":/images/icons/dialog-cancel.png")));
     646        cancel->setText(QApplication::translate("QProgressDialog", "Cancel", "No need to translate this. This translation will be taken from Qt translation files."));
     647        pd.setCancelButton(cancel);
    599648        pd.setMaximum(n);
    600649        pd.setAutoReset(false);
     
    605654        pd.show();
    606655
     656#ifdef Q_OS_WIN32
     657HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID*)&tl);
     658        if (SUCCEEDED(hr)) {
     659                hr = tl->HrInit();
     660                if (FAILED(hr)) {
     661                        tl->Release();
     662                        tl = NULL;
     663                } else {
     664//                      tl->SetProgressState(winId(), TBPF_INDETERMINATE);
     665                        tl->SetProgressValue(winId(), 0, n * 2);
     666                }
     667        }
     668#endif
     669
    607670CTSPSolver solver;
     671        solver.setCleanupOnCancel(false);
    608672        connect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int)));
    609673        connect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel()));
     674#ifdef Q_OS_WIN32
     675        if (tl != NULL)
     676                connect(&solver, SIGNAL(routePartFound(int)), SLOT(solverRoutePartFound(int)));
     677#endif
    610678SStep *root = solver.solve(n, matrix);
     679#ifdef Q_OS_WIN32
     680        if (tl != NULL)
     681                disconnect(&solver, SIGNAL(routePartFound(int)), this, SLOT(solverRoutePartFound(int)));
     682#endif
    611683        disconnect(&solver, SIGNAL(routePartFound(int)), &pd, SLOT(setValue(int)));
    612684        disconnect(&pd, SIGNAL(canceled()), &solver, SLOT(cancel()));
    613685        if (!root) {
    614686                pd.reset();
    615                 if (!solver.wasCanceled())
     687                if (!solver.wasCanceled()) {
     688#ifdef Q_OS_WIN32
     689                        if (tl != NULL) {
     690//                              tl->SetProgressValue(winId(), n, n * 2);
     691                                tl->SetProgressState(winId(), TBPF_ERROR);
     692                        }
     693#endif
     694                        QApplication::alert(this);
    616695                        QMessageBox::warning(this, tr("Solution Result"), tr("Unable to find a solution.\nMaybe, this task has no solution."));
     696                }
     697                pd.setLabelText(tr("Cleaning up..."));
     698                pd.setMaximum(0);
     699                pd.setCancelButton(NULL);
     700                pd.show();
     701#ifdef Q_OS_WIN32
     702                if (tl != NULL)
     703                        tl->SetProgressState(winId(), TBPF_INDETERMINATE);
     704#endif
     705                QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
     706
     707QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false);
     708                while (!f.isFinished()) {
     709                        QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
     710                }
     711                pd.reset();
     712#ifdef Q_OS_WIN32
     713                if (tl != NULL) {
     714                        tl->SetProgressState(winId(), TBPF_NOPROGRESS);
     715                        tl->Release();
     716                        tl = NULL;
     717                }
     718#endif
    617719                return;
    618720        }
     
    621723        pd.setMaximum(solver.getTotalSteps() + 1);
    622724        pd.setValue(0);
     725
     726#ifdef Q_OS_WIN32
     727        if (tl != NULL)
     728                tl->SetProgressValue(winId(), spinCities->value(), spinCities->value() + solver.getTotalSteps() + 1);
     729#endif
    623730
    624731        solutionText->clear();
     
    665772                        pd.show();
    666773                        QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
    667                         solver.cleanup(true);
     774#ifdef Q_OS_WIN32
     775                        if (tl != NULL)
     776                                tl->SetProgressState(winId(), TBPF_INDETERMINATE);
     777#endif
     778QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false);
     779                        while (!f.isFinished()) {
     780                                QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
     781                        }
    668782                        solutionText->clear();
    669783                        toggleSolutionActions(false);
     784#ifdef Q_OS_WIN32
     785                        if (tl != NULL) {
     786                                tl->SetProgressState(winId(), TBPF_NOPROGRESS);
     787                                tl->Release();
     788                                tl = NULL;
     789                        }
     790#endif
    670791                        return;
    671792                }
    672793                pd.setValue(n);
     794#ifdef Q_OS_WIN32
     795                if (tl != NULL)
     796                        tl->SetProgressValue(winId(), spinCities->value() + n, spinCities->value() + solver.getTotalSteps() + 1);
     797#endif
    673798
    674799                cur.beginEditBlock();
     
    713838        pb->setFormat(tr("Generating footer"));
    714839        pd.setValue(n);
     840#ifdef Q_OS_WIN32
     841        if (tl != NULL)
     842                tl->SetProgressValue(winId(), spinCities->value() + n, spinCities->value() + solver.getTotalSteps() + 1);
     843#endif
    715844
    716845        cur.beginEditBlock();
     
    764893        pd.setCancelButton(NULL);
    765894        QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
    766         solver.cleanup(true);
     895#ifdef Q_OS_WIN32
     896        if (tl != NULL)
     897                tl->SetProgressState(winId(), TBPF_INDETERMINATE);
     898#endif
     899QFuture<void> f = QtConcurrent::run(&solver, &CTSPSolver::cleanup, false);
     900        while (!f.isFinished()) {
     901                QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
     902        }
    767903        toggleSolutionActions();
    768904        tabWidget->setCurrentIndex(1);
     905#ifdef Q_OS_WIN32
     906        if (tl != NULL) {
     907                tl->SetProgressState(winId(), TBPF_NOPROGRESS);
     908                tl->Release();
     909                tl = NULL;
     910        }
     911#endif
     912
     913        pd.reset();
     914        QApplication::alert(this, 3000);
    769915}
    770916
     
    833979}
    834980#endif // QT_NO_PRINTER
     981
     982#ifdef Q_OS_WIN32
     983void MainWindow::solverRoutePartFound(int n)
     984{
     985#ifdef Q_OS_WIN32
     986        tl->SetProgressValue(winId(), n, spinCities->value() * 2);
     987#else
     988        Q_UNUSED(n);
     989#endif // Q_OS_WIN32
     990}
     991#endif // Q_OS_WIN32
    835992
    836993void MainWindow::spinCitiesValueChanged(int n)
  • trunk/src/mainwindow.h

    r118 r124  
    3535
    3636#include "tspmodel.h"
     37
     38#ifdef Q_OS_WIN32
     39        // Forward declaration. A real one is in shobjidl.h
     40        struct ITaskbarList3;
     41#endif
    3742
    3843using namespace TSPSolver;
     
    8893        void printPreview(QPrinter *printer);
    8994#endif // QT_NO_PRINTER
     95#ifdef Q_OS_WIN32
     96        void solverRoutePartFound(int n);
     97#endif // Q_OS_WIN32
    9098        void spinCitiesValueChanged(int nCities);
    9199
     
    111119        QRect currentGeometry;
    112120#endif // Q_OS_WINCE_WM
     121
     122#ifdef Q_OS_WIN32
     123        ITaskbarList3 *tl;
     124#endif // Q_OS_WIN32
    113125
    114126        // The solution graph SVG
  • trunk/src/tspsolver.cpp

    r116 r124  
    4343 */
    4444CTSPSolver::CTSPSolver(QObject *parent)
    45         : QObject(parent), nCities(0), total(0), root(NULL) {}
     45        : QObject(parent), cc(true), nCities(0), total(0), root(NULL) {}
    4646
    4747/*!
     
    5151 * \note It is not required to call this function manually. This function is always called by solve() at the beginning of the solution process.
    5252 *
    53  * \sa solve()
     53 * \sa solve(), setCleanupOnCancel()
    5454 */
    5555void CTSPSolver::cleanup(bool processEvents)
    5656{
    57 #ifdef QAPPLICATION_H
    58         if (!processEvents)
    59                 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
    60 #endif
    6157        route.clear();
    6258        mayNotBeOptimal = false;
    6359        if (root != NULL)
    6460                deleteTree(root, processEvents);
    65 #ifdef QAPPLICATION_H
    66         if (!processEvents)
    67                 QApplication::restoreOverrideCursor();
    68 #endif
    6961}
    7062
     
    115107{
    116108        return !mayNotBeOptimal;
     109}
     110
     111/*!
     112 * \brief Sets whether or not to call cleanup() on solution cancel.
     113 * \param enable Set to \c true to enable clenup (default).
     114 *
     115 *  This may be useful if you want to make cleanup yourself or provide indication of clenup to user.
     116 *
     117 * \note Please, note that cleanup() is explicitly called at the start of each solution.
     118 *       Disabling cleanup and forgetting to do it manually may considerably increase the solution time for large tasks (with more than 15 cities).
     119 * \sa cleanup()
     120 */
     121void CTSPSolver::setCleanupOnCancel(bool enable)
     122{
     123        cc = enable;
    117124}
    118125
     
    174181                locker.relock();
    175182                if ((nRow == -1) || (nCol == -1) || canceled) {
    176                         cleanup();
     183                        if (canceled && cc)
     184                                cleanup();
    177185                        return NULL;
    178186                }
  • trunk/src/tspsolver.h

    r116 r124  
    113113        CTSPSolver(QObject *parent = NULL);
    114114        void cleanup(bool processEvents = false);
    115         QString getSortedPath(const QString &city, const QString &separator = " -> ") const;
     115        QString getSortedPath(const QString &city, const QString &separator = QString(" -> ")) const;
    116116        int getTotalSteps() const;
    117117        bool isOptimal() const;
     118        void setCleanupOnCancel(bool enable = true);
    118119        SStep *solve(int numCities, const TMatrix &task);
    119120        bool wasCanceled() const;
     
    131132
    132133private:
    133         bool mayNotBeOptimal, canceled;
     134        bool mayNotBeOptimal, canceled, cc;
    134135        int nCities, total;
    135136        SStep *root;
Note: See TracChangeset for help on using the changeset viewer.