1#!/usr/bin/env perl 2############################################################################# 3## 4## Copyright (C) 2016 The Qt Company Ltd. 5## Contact: https://www.qt.io/licensing/ 6## 7## This file is part of the porting tools of the Qt Toolkit. 8## 9## $QT_BEGIN_LICENSE:LGPL$ 10## Commercial License Usage 11## Licensees holding valid commercial Qt licenses may use this file in 12## accordance with the commercial license agreement provided with the 13## Software or, alternatively, in accordance with the terms contained in 14## a written agreement between you and The Qt Company. For licensing terms 15## and conditions see https://www.qt.io/terms-conditions. For further 16## information use the contact form at https://www.qt.io/contact-us. 17## 18## GNU Lesser General Public License Usage 19## Alternatively, this file may be used under the terms of the GNU Lesser 20## General Public License version 3 as published by the Free Software 21## Foundation and appearing in the file LICENSE.LGPL3 included in the 22## packaging of this file. Please review the following information to 23## ensure the GNU Lesser General Public License version 3 requirements 24## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 25## 26## GNU General Public License Usage 27## Alternatively, this file may be used under the terms of the GNU 28## General Public License version 2.0 or (at your option) the GNU General 29## Public license version 3 or any later version approved by the KDE Free 30## Qt Foundation. The licenses are as published by the Free Software 31## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 32## included in the packaging of this file. Please review the following 33## information to ensure the GNU General Public License requirements will 34## be met: https://www.gnu.org/licenses/gpl-2.0.html and 35## https://www.gnu.org/licenses/gpl-3.0.html. 36## 37## $QT_END_LICENSE$ 38## 39############################################################################# 40 41 42use Cwd; 43use File::Find; 44use File::Spec; 45use IO::File; 46use Getopt::Long; 47use strict; 48use warnings; 49 50my $dry_run = 0; 51my $help = 0; 52my $stripModule = 0; 53my $fixedFileCount = 0; 54my $fileCount = 0; 55my $verbose = 0; 56my $qtdir; 57my $qtIncludeDir; 58 59my $USAGE=<<EOF; 60This script replaces all Qt 4 style includes with Qt 5 includes. 61 62Usage: $0 [options] 63 64Options: 65 --dry-run : Do not replace anything, just print what would be replaced 66 --strip-modules : Strip the module headers for writing portable code 67 --verbose : Verbose 68 --qtdir <directory> : Point to Qt 5's qtbase directory 69EOF 70 71if (!GetOptions('dry-run' => \$dry_run, 'help' => \$help, 72 'strip-modules' => \$stripModule, 'verbose' => \$verbose, 'qtdir:s' => \$qtdir) 73 || $help) { 74 print $USAGE; 75 exit (1); 76} 77 78my %headerSubst = (); 79my $cwd = getcwd(); 80 81sub fixHeaders 82{ 83 my $fileName = $File::Find::name; 84 my $relFileName = File::Spec->abs2rel($fileName, $cwd); 85 86 # only check sources, also ignore symbolic links and directories 87 return unless -f $fileName && $fileName =~ /(\.h|\.cpp|\/C|\.cc|\.CC)$/; 88 89 my $inFile = new IO::File('<' . $fileName) or die ('Unable to open ' . $fileName . ': ' . $!); 90 $fileCount++; 91 my @affectedClasses; 92 my @outLines; 93 94 while (my $line = <$inFile>) { 95 if ($line =~ /^#(\s*)include(\s*)<.*?\/(.*?)>(.*)/) { 96 my $newHeader = $headerSubst{$3}; 97 if ($newHeader) { 98 $line = '#' . $1 . 'include' . $2 . '<' . $newHeader . '>' . $4 . "\n"; 99 push(@affectedClasses, $3); 100 } 101 } elsif ($line =~ /^#(\s*)include(\s*)<QtGui>(.*)/) { 102 $line = '#' . $1 . 'include' . $2 . '<QtWidgets>' . $3 . "\n"; 103 push(@affectedClasses, 'QtGui'); 104 } 105 push(@outLines, $line); 106 } 107 $inFile->close(); 108 109 if (scalar(@affectedClasses)) { 110 $fixedFileCount++; 111 print $relFileName, ': ', join(', ', @affectedClasses), "\n" if ($verbose || $dry_run); 112 if (!$dry_run) { 113 my $outFile = new IO::File('>' . $fileName) or die ('Unable to open ' . $fileName . ': ' . $!); 114 map { print $outFile $_; } @outLines; 115 $outFile->close(); 116 } 117 } else { 118 print $relFileName, ": no modification.\n" if ($verbose || $dry_run); 119 } 120} 121 122sub findQtHeaders 123{ 124 my ($dirName,$includeDir) = @_; 125 126 local (*DIR); 127 128 my $moduleIncludeDir = $includeDir . '/' . $dirName; 129 opendir(DIR, $moduleIncludeDir) || die ('Unable to open ' . $moduleIncludeDir . ': ' . $!); 130 my @headers = readdir(DIR); 131 closedir(DIR); 132 133 foreach my $header (@headers) { 134 next if (-d ($moduleIncludeDir . '/' . $header) || $header =~ /\.pri$/); 135 $headerSubst{$header} = $stripModule ? $header : ($dirName . '/' . $header); 136 } 137} 138 139# -------- MAIN 140 141if ($qtdir) { 142 $qtIncludeDir = $qtdir . '/include'; 143} else { 144 $qtIncludeDir = `qmake -query QT_INSTALL_HEADERS`; 145 chop($qtIncludeDir); 146} 147 148die "The location of the Qt 5 include files could not be determined.\n" 149 ."Please ensure qmake can be found in PATH or pass the command line option --qtdir.\n" 150 unless -d $qtIncludeDir; 151 152findQtHeaders('QtCore', $qtIncludeDir); 153findQtHeaders('QtConcurrent', $qtIncludeDir); 154findQtHeaders('QtWidgets', $qtIncludeDir); 155findQtHeaders('QtPrintSupport', $qtIncludeDir); 156 157if (-d $qtIncludeDir . '/include/QtMultimedia') { 158 findQtHeaders('QtMultimedia', $qtIncludeDir); 159 findQtHeaders('QtMultimediaWidgets', $qtIncludeDir); 160} elsif (-d $qtIncludeDir . '/../qtmultimedia' ) { 161 # This is the case if QTDIR points to a source tree instead of an installed Qt 162 findQtHeaders('QtMultimedia', $qtIncludeDir . '/../qtmultimedia'); 163 findQtHeaders('QtMultimediaWidgets', $qtIncludeDir . '/../qtmultimedia'); 164} 165 166# Support porting from "Qt 4.99" QtDeclarative to QtQuick (QQuickItem et al) 167if (-d $qtIncludeDir . '/include/QtQuick') { 168 findQtHeaders('QtQuick', $qtIncludeDir); 169} elsif (-d $qtIncludeDir . '/../qtdeclarative' ) { 170 # This is the case if QTDIR points to a source tree instead of an installed Qt 171 findQtHeaders('QtQuick', $qtIncludeDir . '/../qtdeclarative'); 172} 173 174# special case 175$headerSubst{'QtGui'} = 'QtWidgets/QtWidgets'; 176 177find({ wanted => \&fixHeaders, no_chdir => 1}, $cwd); 178 179print 'Done. ', ($dry_run ? 'Checked' : 'Modified'), ' ', $fixedFileCount, ' of ', $fileCount, " file(s).\n"; 180